为何NASM/ndisasm将相对jmp/call指令的操作数显示为绝对地址?
x86相对跳转/调用指令反汇编显示差异的解答
核心结论
这种机器码存储相对偏移、反汇编助记符显示绝对地址的行为是完全符合预期的,属于反汇编工具的常规设计,和指令集规范、汇编器实现都没有冲突。
详细解释
指令集的本质要求
x86指令集里,EB cb对应的JMP rel8确实是相对偏移指令:操作码后的cb字节是相对于「下一条指令的IP值」的有符号偏移量,这是硬件执行的底层逻辑,机器码必须严格遵循这个规则。你测试中看到的EB00是完全正确的——因为jmp label的下一条指令就是label处的nop,相对偏移量为0。反汇编工具的可读性优化
反汇编器(比如你用的ndisasm)的核心目标是把机器码翻译成人类易读的汇编代码。对于相对跳转/调用指令,工具会自动计算偏移对应的绝对内存地址显示在助记符中,而非直接输出原始的偏移字节:
- 你的测试里,
jmp short 0x7中的0x7是label的绝对地址,而机器码里的00是相对偏移(下一条指令的IP正好是0x7,偏移量为0)。 - 当你在JMP前添加更多NOP时,
label的绝对地址会变化,所以反汇编显示的操作数会跟着变,但跳转指令和目标指令的相对距离始终是0,因此机器码的EB00不会改变。
工具行为的普遍性
几乎所有主流反汇编器(比如IDA Pro、GDB反汇编、objdump)都会采用这种显示逻辑——直接展示绝对地址比让开发者手动计算相对偏移要直观得多,能快速定位目标位置。而汇编器(如nasm、gas)在处理jmp label这类符号时,会自动计算正确的相对偏移并编码到机器码中,完全符合指令集规范。相对CALL指令的相同逻辑
相对CALL指令(比如E8 cd对应的CALL rel32)和JMP的处理逻辑完全一致:机器码存储的是相对于下一条指令的偏移,反汇编时会显示目标的绝对地址,这同样是工具为可读性做的优化,并非指令集的特殊要求。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

