大会 - 86 call指令和内存地址?

问题描述 投票:4回答:1

我一直在读一些汇编代码,我已经开始看到的是调用指令计数器相对程序实际上是。

但是,每当我使用Visual Studio或WinDBG的调试,它总是说叫0XFFFFFF ......这对我来说意味着它在说我要跳转到该地址。

谁是谁非?是Visual Studio中隐藏指令编码的复杂性,只是说哦,是这样的计划意味着什么,那就是调试器知道这是一个PC相关的指令,并且因为它知道个人电脑,它只是和做数学的吗?

非常困惑。

assembly linker x86 nasm masm
1个回答
4
投票

如果你正在拆卸那些尚未关联.o目标文件,调出地址将只是通过链接填写的占位符。

您可以使用objdump -drwc -Mintel.o表明搬迁类型+符号的名称(-r的选择是关键。或者-R一个已经连接的共享库。)


这是对用户更有用,显示跳转目标的实际地址,而不是拆解为jcc eip-1234H什么的。目标文件有一个默认加载地址,所以拆装具有在每一个指令eip的值,这通常出现在反汇编输出。

例如在一些汇编代码我写的(在这里我使用了它成目标文件的符号名称,因此该循环分支目标实际上是可见的反汇编):

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指令的编码是一个有符号小尾数32位位移的-0xD0字节。 (跳跃的排量增加e/rip的跳转后的值,跳转指令本身是6个字节长,所以排量必须是-0xD0,不只是-0xCA0x100 - 0xD0 = 0x30,这是对最不显著字节的值2的补位移。

在你的问题,你在谈论呼叫地址为0xFFFF...,这没有什么意义,除非这只是一个占位符,或者您认为非0xFF字节位移是操作码的一部分。

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

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从节开始的指令。另call有不同的目标地址,因为它是在文件在不同的地方。 (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位相对地址被支撑,与操作数大小前缀,我想节省一个指令字节。)

© www.soinside.com 2019 - 2024. All rights reserved.