我正在学习 64 位 nasm,我通过执行以下操作组装了仅包含 64 位寄存器的 .nasm 文件
nasm -f elf64 HelloWorld.nasm -o HelloWorld.o
并链接它做以下
ld HelloWorld.o -o HelloWorld
当我运行
file
命令时,程序运行正确,甚至说它是 64 位 ELF,但是当我使用 objdump
或 gdb
反汇编可执行文件时,我将寄存器作为 64 位寄存器放入代码在反汇编时显示为 32 位寄存器。 (例如:源中的rax
在反汇编时显示为eax
)
这是为什么?
这种情况不会只发生在一台电脑上,而且是一个新问题,以前没有出现过。
HelloWorld.nasm:
global _start
section .text
_start:
mov rax, 1
mov rdi, 1
mov rsi, hello_world
mov rdx, length
syscall
mov rax, 60
mov rdi, 11
syscall
section .data
hello_world: db 'Hello World',0xa
length: equ $-hello_world
反汇编的 HelloWorld:
...
00000000004000b0 <_start>:
4000b0: b8 01 00 00 00 mov eax,0x1
4000b5: bf 01 00 00 00 mov edi,0x1
4000ba: 48 be d8 00 60 00 00 movabs rsi,0x6000d8
4000c1: 00 00 00
4000c4: ba 0c 00 00 00 mov edx,0xc
4000c9: 0f 05 syscall
4000cb: b8 3c 00 00 00 mov eax,0x3c
4000d0: bf 0b 00 00 00 mov edi,0xb
4000d5: 0f 05 syscall
...
为什么
...
mov rax, 1
mov rdi, 1
mov rsi, hello_world
...
被拆解为
...
4000b0: b8 01 00 00 00 mov eax,0x1
4000b5: bf 01 00 00 00 mov edi,0x1
4000ba: 48 be d8 00 60 00 00 movabs rsi,0x6000d8
4000c1: 00 00 00
...
因为文字
0x1
适合32位,而64位寄存器的高32位在通过相应的0
寄存器加载低32位时设置为E
。因此,汇编程序可以将 mov
优化为 32 位操作。
请注意,加载到
rsi
中的地址可能不适合 32 位,因此 rsi
保持原样。
如果加上下面的说明,可以很清楚的看到效果:
mov rbx, 0x0ffffffff ; still fits into 32 bit
mov rbx, 0x100000000 ; does not fit into 32 bits anymore
被拆解为
a: bb ff ff ff ff mov $0xffffffff,%ebx
f: 48 bb 00 00 00 00 01 movabs $0x100000000,%rbx
16: 00 00 00
您可以使用
-O0
禁用 nasm 优化,在这种情况下,指令将保留其长格式:
nasm -O0 -f elf64 HelloWorld.asm
结果:
14: 48 bb ff ff ff ff 00 movabs $0xffffffff,%rbx
1b: 00 00 00
1e: 48 bb 00 00 00 00 01 movabs $0x100000000,%rbx
25: 00 00 00