我正在阅读AMD64手册,在Call Near部分,它说:
对于64位模式下的近调用,操作数大小默认为64位。E8操作码
导致RIP=RIP+32位有符号位移,FF/2操作码导致
RIP=寄存器或内存的64位偏移量。没有可用于编码32位的前缀
64位模式下的操作数大小。
看起来每次操作码是e8,接下来的32位就被用作偏移量,对吧?我反汇编了一个程序,试着:
4003f0: e8 3b 00 00 00 callq 400430 <__gmon_start__@plt>
根据手册,目标地址应该是0x4003f0+0x3b。如果您尝试,结果是0x40042b,但根据objdump,应该是0x400430。我试过其他的呼叫指令,同样的4个字节丢失了,有人知道原因吗?
另外:它说操作数大小默认为64位,然后说当操作码为E8时只考虑32位,这是个例外吗?
最佳答案
只是回答为什么它是0x400430
而不是0x40042b
。当指令从0x4003f0
开始时,eip计算基于它的下一条指令,因此必须将5(当前指令的长度)添加到eip。
目标操作数指定代码段中的绝对偏移量(与代码段基部的偏移量)或相对偏移量(相对于EIP寄存器中指令指针的当前值的有符号位移量;该值指向调用指令之后的指令)。
(摘自英特尔手册。)