gpt4 book ai didi

汇编-x86调用指令和内存地址?

转载 作者:行者123 更新时间:2023-12-03 06:36:09 34 4
gpt4 key购买 nike

我一直在阅读一些汇编代码,并且开始发现调用指令实际上是与程序计数器相关的。

但是,每当我使用 Visual Studio 或 Windbg 进行调试时,它总是显示 call 0xFFFFFF ...这对我来说意味着它说我要跳转到该地址。

谁是对的? Visual Studio 是否隐藏了指令编码的复杂性,只是说哦,这就是程序的含义,即调试器知道它是与 PC 相关的指令,并且由于它了解 PC,因此它会为您进行数学计算?

非常困惑。

最佳答案

如果您要反汇编尚未链接的 .o 目标文件,则调用地址将只是一个由链接器填充的占位符。

您可以使用objdump -drwc -Mintel显示来自.o的重定位类型+符号名称 (-r 选项是关键。或者 -R 用于已链接的共享库。)

<小时/>

对用户显示跳转目标的实际地址更有用,而不是将其反汇编为jcc eip-1234H之类的。目标文件有一个默认的加载地址,因此反汇编器在每条指令上都有一个 eip 值,这通常出现在反汇编输出中。

例如在我编写的一些 asm 代码中(我使用将其放入目标文件的符号名称,因此循环分支目标实际上对反汇编程序可见):

objdump -M intel  -d rs-asmbench:
...
00000000004020a0 <.loop>:
4020a0: 0f b6 c2 movzx eax,dl
4020a3: 0f b6 de movzx ebx,dh
...
402166: 49 83 c3 10 add r11,0x10
40216a: 0f 85 30 ff ff ff jne 4020a0 <.loop>

0000000000402170 <.last8>:
402170: 0f b6 c2 movzx eax,dl

请注意,jne 指令的编码是 -0xD0 字节的有符号小端 32 位位移。 (跳转将其位移添加到跳转后的e/rip值中。跳转指令本身有6个字节长,因此位移必须为-0xD0,而不仅仅是-0xCA。)0x100 - 0xD0 = 0x30,这是 2 的补码位移的最低有效字节的值。

在你的问题中,你所说的调用地址是0xFFFF...,这没有什么意义,除非那只是一个占位符,或者你认为非0xFF code> 位移中的字节是操作码的一部分。

链接之前,对外部符号的引用如下所示:

objdump -M intel -d main.o
...
a5: 31 f6 xor esi,esi
a7: e8 00 00 00 00 call ac <main+0xac>
ac: 4c 63 e0 movsxd r12,eax
af: ba 00 00 00 00 mov edx,0x0
b4: 48 89 de mov rsi,rbx
b7: 44 89 f7 mov edi,r14d
ba: e8 00 00 00 00 call bf <main+0xbf>
bf: 83 f8 ff cmp eax,0xffffffff
c2: 75 cc jne 90 <main+0x90>
...

请注意 call 指令的相对位移 = 0。因此,在链接器插入实际相对值之前,它们会使用以下目标对 call 进行编码:通话后立即发出指示。 (即RIP = RIP+0)。 call bf 后面紧跟着一条指令,该指令从该节开头的 0xbf 开始。另一个调用具有不同的目标地址,因为它位于文件中的不同位置。 (gcc 将 main 放在自己的部分:.text.startup)。

因此,如果您想了解实际调用的内容,请查看链接的可执行文件,或者获取一个反汇编程序,该反汇编程序查看目标文件符号以插入调用目标的符号名称,而不是将它们显示为调用零位移。

在链接之前,到本地符号的相对跳转已经得到解决:

objdump -Mintel  -d asm-pinsrw.o:
0000000000000040 <.loop>:
40: 0f b6 c2 movzx eax,dl
43: 0f b6 de movzx ebx,dh
...
106: 49 83 c3 10 add r11,0x10
10a: 0f 85 30 ff ff ff jne 40 <.loop>
0000000000000110 <.last8>:
110: 0f b6 c2 movzx eax,dl

请注意,即使文件没有基地址,在相对跳转到同一文件中的符号时也使用完全相同的指令编码,因此反汇编程序仅将其视为零。

请参阅英特尔的指令编码引用手册。链接 https://stackoverflow.com/tags/x86/info 。即使在 64 位模式下,call 也仅支持 32 位符号扩展相对偏移量。支持 64 位绝对地址。 (在32位模式下,支持16位相对地址,带有操作数大小前缀,我猜可以节省一个指令字节。)

关于汇编-x86调用指令和内存地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31818870/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com