26

何らかの理由で、このコードをコンパイルしようとすると、コンパイラは次のように言います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, #300とを実行して一時的に修正しましたadd r7, #70。これにより、目的の効果が得られます。ただし、エラーの原因はまだわかりません。

4

1 に答える 1

49

ARM v5 までの ARM 命令セットは、限られた範囲の即値しか使用できません。問題は、命令自体で値をエンコードする必要があることです。すべての ARM 命令は 32 ビット幅であるため、ARMv5 までの元の命令セットには、即値をエンコードするための合計 8 + 4 ビットしかありませんでした。最初の 8 ビットは 0 ~ 255 の範囲の任意の 8 ビット値をロードでき、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 ビット値を上半分にロードするために使用することもできます。

于 2012-04-21T18:25:04.017 に答える