Intel x86到ARM汇编转换

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

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

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

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

 /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)

回答问题1

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

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

  • 0-255
  • 256,260,264,…,1020
  • 1024,1040,1056,…,4080
  • 等等

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

 LDR r0, =0x0804c000 

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

回答问题2

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

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

ARM不使用英特尔语法,它使用ARM语法。

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

ARM,Mips和其他公司的目标是固定字长。 那么你如何适应一条指令,说明立即移动到一个寄存器,指定寄存器,并将32位立即数置于32位? 不可能。 因此,对于固定长度的指令集,您不能简单地将任何想要的符号加载到任何寄存器中。 您必须阅读该指令集的规则。 mips允许16位立即,arm为8加或减,具体取决于arm指令集的味道和指令。 mips限制你可以将这16位设置为高或低,arm允许你将这8位放在32位寄存器中的任何位置,具体取决于arm指令集(arm,thumb,thumb2 extensions)的风格。

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

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

对于CISC来说,立即简单地将其添加到指令中,因此无论是0字节还是20字节,它仍然存在于任何一种方法中。

ARM汇编程序通常也允许您使用此快捷方式:

 ldr r0,=something ... something: 

其中说r0用ADDRESS的东西加载,而不是那个位置的内容而是地址(比如lea)

但这有助于实现这一直接捷径

 ldr r0,=0x12345678 

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