9

我目前正在学习ARM汇编语言;

为此,我试图将一些转换x86 code (AT&T Syntax)为 ARM 汇编(Intel Syntax)代码。

__asm__("movl $0x0804c000, %eax;");

__asm__("mov R0,#0x0804c000");

从这个文档中,我了解到在 x86 中,堆结构的 Chunk 1 从 0x0804c000 开始。但是当我尝试在 中做同样的事情时arm,我收到以下错误:

/tmp/ccfNZp9F.s:174: Error: invalid constant (804c000) after fixup

我假设问题是 ARM 只能加载32 位指令。

Question 1: Any idea what would be the first chunk in case of ARM processors?


Question 2:

从我之前的问题中,我知道内存间接寻址是如何工作的。

下面写的片段是否做同样的工作?

movl (%eax), %ebx

LDR R0,[R1]

我在用ARMv7 Processor rev 4 (v7l)

4

2 回答 2

7

尝试通过查看 x86 来学习 arm 并不是一个好主意,一个是 CISC,非常丑陋,另一个是 RISC,而且更干净。只需通过查看架构参考手册中的指令集参考来学习 ARM。查找 mov 指令、add 指令等。

ARM 不使用 intel 语法,它使用 ARM 语法。

不要用内联汇编来学习,写真正的汇编。首先使用指令集模拟器而不是硬件。

ARM、Mips 和其他公司的目标是固定字长。那么,例如,您将如何适应将一些立即数移至寄存器、指定寄存器并将 32 位立即数全部放入 32 位的指令?不可能。因此,对于固定长度的指令集,您不能简单地将所需的任何立即数加载到任何寄存器中。您必须阅读该指令集的规则。mips 允许 16 位立即数,arm 为 8 加或减,具体取决于 arm 指令集和指令的风格。mips 限制了您可以将这 16 位置于高位或低位的位置,arm 允许您将这 8 位置于 32 位寄存器中的任何位置,具体取决于 arm 指令集的风格(arm、thumb、thumb2 扩展)。

与大多数汇编语言一样,您可以通过执行以下操作来解决此问题

ldr r0,my_value
...
my_value: .word 0x12345678

使用 CISC,立即数只是简单地附加到指令上,因此无论是 0 字节的距离还是 20 字节的距离,它仍然存在于任何一种方法中。

ARM 汇编器通常还允许您使用以下快捷方式:

ldr r0,=something
...
something:

表示用某物的地址加载 r0,而不是该位置的内容,而是地址(如 lea)

但这适用于这种直接的捷径

ldr r0,=0x12345678

如果汇编器支持,它将分配一个内存位置来保存该值并生成一个 ldr r0,[pc,offset] 指令来读取它。如果立即数在 mov 的规则内,那么汇编器可能会将其优化为 mov rd,#immediate。

于 2013-06-25T13:52:49.130 回答
2

回答问题 1

ARM 上的 MOV 指令只有 12 位可用于立即数,而这些位是这样使用的:8 位用于值,4 位用于指定向右旋转的次数(旋转次数乘以 2,增加范围)。

这意味着该指令只能使用有限数量的值。他们是:

  • 0-255
  • 256、260、264、...、1020
  • 1024, 1040, 1056, ..., 4080
  • ETC

等等。您收到该错误是因为无法使用 8 位 + 旋转创建常量。您可以按照以下指令将该值加载到寄存器中:

LDR r0, =0x0804c000

请注意,这是一条伪指令。汇编器基本上会将该常量放在代码中的某个位置,并将其作为内存位置加载,并与 PC(程序计数器)有一些偏移。

回答问题 2

是的,这些说明是等效的。

于 2013-06-25T13:51:17.093 回答