【发布时间】:2011-09-28 11:30:44
【问题描述】:
我了解在 x86_64 程序集中有例如(64 位)rax 寄存器,但它也可以作为 32 位寄存器、eax、16 位、ax 和 8 位等来访问。在什么情况下我不会只使用完整的 64 位,为什么,会有什么优势?
以这个简单的 hello world 程序为例:
section .data
msg: db "Hello World!", 0x0a, 0x00
len: equ $-msg
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, msg ; The address of hello_world string
mov rdx, len ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
至少,rdi 和 rdx 只需要 8 位而不是 64 位,对吧?但是,如果我将它们分别更改为 dil 和 dl(它们的低 8 位等效项),程序会进行汇编和链接,但不会输出任何内容。
但是,如果我使用 eax、edi 和 edx,它仍然有效,所以我应该使用它们而不是完整的 64 位吗?为什么或为什么不?
【问题讨论】:
-
实际上在 Linux 中(可能还有其他一切?)系统调用的参数是 32 位宽的,因此您应该使用 EDI 和 EDX。 win.tue.nl/~aeb/linux/lk/lk-4.html#ss4.3
-
rax 怎么样,也应该改为 eax 吗?我尝试更改这 3 个并且它有效,但我想知道为什么我应该这样做以及有什么优势。
-
在这个程序的情况下,唯一明显的区别是文字值(4、1、0 等)在 64 位时是两倍大,所以你的程序将大几个字节,理论上,从磁盘/内存加载到 CPU 可能需要更长的时间。
-
所以没有理由在不需要时使用完整的 64 位,对吧? (我知道也没有理由手动进行代码组装,但我只是想确保......)
-
@MattyK:
mov r64, sign-extended-imm32是 7 个字节,而mov r32, imm32是 5 个字节。在 GAS 中,您可以使用movabs请求mov r64, imm64,但 NASM/YASM 仅根据常量的大小选择该编码。 (事实上,当您将目标写为rdi时,NASM 会将小常量优化为mov r32, imm32。我不确定符号地址;如果您不使用“small”,它可能会将它们保留为imm64代码模型,并且您的符号地址约为 32 位。但它不会将mov rdi,0优化为xor edi,edi,因为对标志有副作用。)
标签: assembly 64-bit x86-64 nasm cpu-registers