C 英特尔x86到ARM程序集转换
我目前正在学习汇编语言 为此,我尝试将一些C 英特尔x86到ARM程序集转换,c,x86,arm,intel-syntax,C,X86,Arm,Intel Syntax,我目前正在学习汇编语言 为此,我尝试将一些x86代码(AT&T语法)转换为ARM汇编(英特尔语法)代码 __asm__("movl $0x0804c000, %eax;"); __asm__("mov R0,#0x0804c000"); 由此,我了解到在x86中,堆结构的块1从0x08040000开始。但当我尝试在arm中执行相同操作时, 我得到以下错误: /tmp/ccfNZp9F.s:174: Error: invalid constant (804c000) after fixup
x86代码(AT&T语法)
转换为ARM汇编(英特尔语法)
代码
__asm__("movl $0x0804c000, %eax;");
__asm__("mov R0,#0x0804c000");
由此,我了解到在x86中,堆结构的块1从0x08040000开始。但当我尝试在arm中执行相同操作时,
我得到以下错误:
/tmp/ccfNZp9F.s:174: Error: invalid constant (804c000) after fixup
我假设问题在于ARM只能加载指令
Question 1: Any idea what would be the first chunk in case of ARM processors?
Question 2:
从上一篇文章中,我知道内存间接寻址是如何工作的
下面写的代码片段是否也在做同样的工作
movl (%eax), %ebx
LDR R0,[R1]
我使用的是ARMv7处理器rev 4(v7l)
对问题1的回答
ARM上的MOV指令只有12位可用于立即值,这些位的使用方式是:8位用于值,4位用于指定向右旋转的次数(旋转次数乘以2,以增加范围)
这意味着该指令只能使用有限数量的值。它们是:
- 0-255
- 256,260,264,…,1020
- 102410401056,…,4080
- 等
LDR r0, =0x0804c000
请注意,这是一条伪指令。汇编器基本上会将该常量放在代码中的某个地方,并将其作为内存位置加载,并将其偏移到PC(程序计数器)上
对问题2的回答
是的,这些指令是等效的。通过查看x86来学习arm不是一个好主意,一个是CISC,非常难看,另一个是RISC,更干净。。只需通过查看架构参考手册中的说明集参考来学习ARM。查找mov指令、add指令等 ARM不使用intel语法,而是使用ARM语法 不要通过使用内联汇编来学习,而是编写真正的汇编。首先使用指令集模拟器,而不是硬件 ARM、Mips和其他工具的目标是固定字长。例如,您将如何适应这样一条指令:将某个立即数移动到寄存器,指定寄存器,并将32位立即数全部放入32位?不可能。因此,对于固定长度的指令集,您不能简单地将任何需要的立即数加载到任何寄存器中。你必须仔细阅读该指令集的规则。mips允许16位即时,arm允许8加减,具体取决于arm指令集和指令的风格。mips限制您可以将这16位放入高位或低位,arm允许您根据arm指令集(arm、thumb、thumb2扩展名)的风格将这8位放入32位寄存器的任何位置 与大多数汇编语言一样,您可以通过这样做来解决这个问题
ldr r0,my_value
...
my_value: .word 0x12345678
对于CISC,immediate只是简单地附加到指令上,因此无论是0字节一路还是20字节一路,无论采用哪种方法,它都仍然存在
ARM汇编程序通常还允许您使用以下快捷方式:
ldr r0,=something
...
something:
这表示用某物的地址加载r0,而不是该位置的内容,而是地址(如lea)
但这有助于找到这条捷径
ldr r0,=0x12345678
如果汇编程序支持,它将分配一个内存位置来保存该值,并生成一条ldr r0、[pc,offset]指令来读取该值。如果立即数在mov的规则范围内,那么汇编器可能会将其优化为mov rd,#立即数。请参阅:以及我在此处标记的所有重复项。ARM仅支持按2的倍数旋转的8位常量。为了支持像您这样的常量,使用语法
ldr r0,=0x804c000
。汇编程序维护一个文本池并将常量放在那里。使用PC
相对寻址加载常量。使用指令.ltorg
在汇编程序中转储池。因为ARM是risc,而x86是cisc,而且它们只是不同的指令集,所以只有一小部分x86代码会直接“移植”到一个。每个x86可能需要多条ARM指令(有时反之亦然,一组x86指令需要一条ARM指令)。所有处理器都有类似的功能,如寄存器间接寻址,是的,这两个功能相同。ARM语法到底是什么?
Intel语法是英特尔手册中为英特尔处理器定义的语法。AT&T语法是AT&T对其汇编程序的偏离。这两者都与x86以外的任何其他处理器无关。将这些术语应用于ARM、MIPS、AVR、6502、PDP11或任何其他处理器都毫无意义。原始供应商指令集参考中定义的语法是供应商语法,供应商通常制作或已经制作了使用相关语法的汇编程序。但是,任何一个编写汇编程序的人都可以在他们认为合适的时候修改语法,因为汇编语言实际上没有标准,机器代码是标准的,不管你怎么做,你怎么做。以gnu汇编程序对汇编语言所做的工作为例,谢谢。当我尝试使用LDR r0时,=0x0804c000。下面是汇编程序消息:偏移量超出范围
将.ltorg放在加载该值的位置附近。这将把文字池放在那里,这将解决偏移问题。.ltorg
正是我所描述的。这是一个文字池;汇编程序放置以满足ldr r0、=0x804c000
请求的常量数据。也许有帮助?或和在gnu汇编程序手册中。只需在偶尔返回的子程序后添加文本.ltorg
,这就是您需要知道的所有内容。@artlessnoise:谢谢。只有一个问题:如果我想将数据从r0加载到另一个寄存器,我会执行