因此,我正在学习 ARM 汇编,并遇到了两种从内存加载数据的方法。
方法 1:使用“=”运算符
.section .data
number: .word 0x8
.section .text
.global _start
_start:
LDR R1, =number
LDR R1, [R1]
Run Code Online (Sandbox Code Playgroud)
方法 2:使用文字池
.section .data
number: .word 0x8
.section .text
.global _start
_start:
LDR R1, address_of_number
LDR R1, [R1]
address_of_number: .word number
Run Code Online (Sandbox Code Playgroud)
这两种方法都做同样的事情。它们加载number该.data部分中存在的地址,然后加载存储在该地址的实际值。
所以我想知道这两种方法有区别吗?我读到该=运算符与C中的类似。*那么使用Literal Pool whereexistsaddress_of_number来存储地址的目的是什么?
首先,汇编语言特定于工具而不是目标。并非所有 ARM 汇编器都支持此语法,并且支持它的汇编器也不能同等支持该语法。我的理解是,gnu 在这个地址方面是功能最丰富的。
第二……试试吧……
ldr r0,=0x1234567
nop
nop
nop
Disassembly of section .text:
00000000 <.text>:
0: e59f0008 ldr r0, [pc, #8] ; 10 <.text+0x10>
4: e1a00000 nop ; (mov r0, r0)
8: e1a00000 nop ; (mov r0, r0)
c: e1a00000 nop ; (mov r0, r0)
10: 01234567 .word 0x01234567
Run Code Online (Sandbox Code Playgroud)
或者
ldr r0,hello
nop
nop
nop
hello: .word 0x12345678
Disassembly of section .text:
00000000 <hello-0x10>:
0: e59f0008 ldr r0, [pc, #8] ; 10 <hello>
4: e1a00000 nop ; (mov r0, r0)
8: e1a00000 nop ; (mov r0, r0)
c: e1a00000 nop ; (mov r0, r0)
00000010 <hello>:
10: 12345678 .word 0x12345678
Run Code Online (Sandbox Code Playgroud)
相同的机器码,没有区别。
但如果你这样做
ldr r0,=0x00000104
ldr r0,=0x11000000
ldr r0,=0x20000001
ldr r0,=0x0ffffff0
Disassembly of section .text:
00000000 <.text>:
0: e3a00f41 mov r0, #260 ; 0x104
4: e3a00411 mov r0, #285212672 ; 0x11000000
8: e3a00212 mov r0, #536870913 ; 0x20000001
c: e3e002ff mvn r0, #-268435441 ; 0xf000000f
Run Code Online (Sandbox Code Playgroud)
gnu 汇编器至少会为您选择不同的指令(ldr .. = 是伪指令)(其他汇编器可能不会,也不一定期望这样做)。
但正如预期的那样,如果您:
ldr r0,hello
nop
nop
nop
hello: .word 0x11000000
Run Code Online (Sandbox Code Playgroud)
你得到
Disassembly of section .text:
00000000 <hello-0x10>:
0: e59f0008 ldr r0, [pc, #8] ; 10 <hello>
4: e1a00000 nop ; (mov r0, r0)
8: e1a00000 nop ; (mov r0, r0)
c: e1a00000 nop ; (mov r0, r0)
00000010 <hello>:
10: 11000000 .word 0x11000000
Run Code Online (Sandbox Code Playgroud)
有时您可能希望准确控制池的位置,或者您可能特别希望强制执行与 PC 相关的负载。或者希望像人们通常希望用汇编语言那样一对一地控制一切。
现在如果你知道编码是如何工作的
mov r0,#0x00000104
mov r0,#0x00000101
test.s: Assembler messages:
test.s:3: Error: invalid constant (101) after fixup
Run Code Online (Sandbox Code Playgroud)
第一个将编码第二个不会(早期的手臂指令)。然后你必须返回并将代码更改为 ldr r0,=
以 ldr = 开头或以 ldr = 结尾是个人喜好。现在你需要了解有多种arm指令集和不同的架构版本。Thumb、thumb2 和 arm 具有不同的直接编码规则,因此适用于其中之一的规则不一定适用于另一个。但是,至少对于 gnu 汇编器,ldr = 将选择最佳指令。