在x86-64 Tour of Intel Manuals中,我读到了
也许最令人惊讶的事实是,诸如
MOV EAX, EBX自动将指令的高32位归零的指令RAX.
同一来源引用的英特尔文档(3.4.1.1 64位手动基本架构中的通用寄存器)告诉我们:
- 64位操作数在目标通用寄存器中生成64位结果.
- 32位操作数生成32位结果,在目标通用寄存器中零扩展为64位结果.
- 8位和16位操作数生成8位或16位结果.目标通用寄存器的高56位或48位(分别)不会被操作修改.如果8位或16位操作的结果用于64位地址计算,则将寄存器显式符号扩展为完整的64位.
在x86-32和x86-64汇编中,16位指令如
mov ax, bx
Run Code Online (Sandbox Code Playgroud)
不要表现出这种"奇怪"的行为,即eax的上层词被归零.
因此:引入这种行为的原因是什么?乍一看似乎不合逻辑(但原因可能是我习惯了x86-32汇编的怪癖).
为了使call绝对地址正常(接近直接相对),在您编写的 NASM 或 AT&T 语法中call 0x1234567,汇编器 + 链接器负责计算 arel32以从链接器放置call指令的任何位置到达该目标。
例如,在 Linux 上用 将其组装成静态 64 位 ELF 可执行文件yasm -felf64 foo.asm && ld foo.o -o foo,然后用 反汇编objdump -drwC -Mintel foo为您提供:
foo: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: e8 e2 44 e3 00 call 1234567 <_end+0xc344df>
Run Code Online (Sandbox Code Playgroud)
链接器根据目标文件中的重定位计算了0x1234567从到达的正确 rel32 :0x400080+5R_X86_64_PC32
0: e8 00 00 00 00 call 5 <_start+0x5> 1: R_X86_64_PC32 *ABS*+0x1234563
Run Code Online (Sandbox Code Playgroud)
你如何让 MASM …