web-dev-qa-db-ja.com

修正後の無効な定数?

何らかの理由で、このコードをコンパイルしようとすると、コンパイラーはsyscall.s:72:invalid constant (0x172) after fixupと言います。

.globl _mach_msg_trap$MACH
_mach_msg_trap$MACH:
    stmfd sp!, {r4,r7}
    mov r7, #370 /* this is line 72 */
    svc 0
    ldmfd sp!, {r4, r7}
    bx lr

なぜそれをしているのか分かりません。小さい定数をr7に入れると、うまく機能します。しかし、数値が大きいほど、このエラーが発生します。 mov r7, #300add r7, #70を実行して一時的に修正しました。これにより、目的の効果が得られます。エラーの原因はまだわかりません。

24
Kristina Brooks

ARM命令は、movを使用して限られた範囲の即値のみをロードできます。問題は、値がmov命令自体にエンコードされる必要があることです。すべてのARM命令は32ビット幅であり、ARMv5までの元の命令セットは即値をエンコードするために合計で8 + 4ビットしかありませんでした。最初の8ビットは、任意の8ビット値intをロードできます。 0〜255の範囲で、4ビットは右に回転し、0〜30の間で2ずつステップします。

したがって、次のような値をロードできます。

#0
#122
#121 ror #24 = 30976
#230 ror #12 = 241172480

ただし、#370はこのスキームではロードできません。#185 ror #31のようなものは必要ですが、これは不可能です。

現在の値をロードするには2つの方法があります。

  1. 複数のステップで値を構成することにより、すでにそれをどのように解決したか。
  2. Ldrを使用してメモリから値をロードすることにより:ldr r7,=#370次に、アセンブラは定数プールを作成し、pc相対アドレッシングを介してそこから値をロードします。

通常、2つまでの命令で定数を作成することをお勧めします。それが不可能な場合(または値を再配置可能にする必要がある場合)は、ldrを使用します。

ARMv7以降では、movwを使用してレジスタの下半分にある16ビット値をロードしながら上半分をゼロにし、movtを使用して別の16ビット値をタッチせずに上半分にロードすることもできます。下半分。

43
Nico Erfurth