x86_64汇编之三:x86_64汇编和x86_32汇编的区别

1. 地址、操作数、寄存器使用上的区别

x86_32汇编中的大部分指令在x86_64中都有对应,功能相同,只不过x86_64上的对应指令可能支持操作64位的地址、操作数和寄存器。

需要注意的是,x86_64中操作的地址不一定非得是64位,也可以是32位的。例如,x86_64支持下面的指令:

mov r10, [eax]

其中,eax的内容就是地址,这个32位的地址前面会被补上32位的0,也就是说,eax 只能寻址内存空间的低4GB。通常是不推荐使用32位的地址的,推荐使用64位。

此外,x86_64指令所操作的寄存器和操作数并也不非得是64位,也可以操作8位、16位、32位的寄存器或数。

  • 以通用寄存器RAX为例,在64位机器上,不仅可以操作RAX,还可以操作EAX,AX,AH,AL。
  • 再举个例子,x86_64汇编指令的立即数可以是8位、16位、32位、64位的,参考:https://wiki.osdev.org/X86-64_Instruction_Encoding#Immediate

说到立即数,需要额外注意一下。x86_64的汇编指令中并非所有指令都支持64位的立即数

  • 绝大多数指令最多支持32位的立即数。以pushq指令为例,pushq $0x1122334455667788指令尝试push一个64位的立即数,这会导致编译错误。
    那么,如果我们是在一个64位的上下文中使用32位的立即数,会怎么样呢?这个32位的立即数将会被符号扩展成64位的。
  • 只有mov指令是一个特例,它可以支持64位的立即数

参考:https://stackoverflow.com/questions/13351363/push-on-64bit-intel-osx

2. x86_64汇编指令操作8/16/32位寄存器时存在的问题

虽然x86_64汇编指令支持操作8/16/32位的寄存器,但是这样做可能会产生某些副作用。

RAX/EAX寄存器为例,假设一开始RAX的内容是0x8000000000000000。执行add eax, 10指令,会导致RAX高32位被清0,然后低32位才加上10,所以结果是0x000000000000000A

但是,当使用x86_64汇编指令操作8位寄存器AL和16位寄存器AX时,却不会导致高位清0,高位保持不变。

此外,x86_64还规定了如果一个指令使用了AH, BH, CH, DH其中一个寄存器,那么该指令就不能再使用SIL, DIL, BPL, SPL, R8B - 15B这些8位寄存器。

3. x86_64不支持的x86_32指令

有些x86_32指令在x86_64中不再被支持,如下表所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_29328443/article/details/107198854