使用objdump时确定寄存器值

Sam*_*Sam 6 x86 assembly x86-64 objdump control-flow

所以我试图使用objdump实用程序从程序集构建一个控制流图,我遇到了一个问题.基本上,每当分支发生且目标地址相对时,我不知道如何知道下一个基本块的起始位置.我不确定我是否清楚,所以我会添加一个例子.假设我的程序正在通过objdump输出,并记录了第一个基本块的起始地址.然后它命中一个跳转命令,该命令使用相对寻址指向要跳转到的正确地址.我知道我的第一个基本块的结束就在那里,但是如何在下一个基本块的开头找到正确的地址呢?任何人都可以提供的任何指导都会非常感激,我最多只是x86的新手,过去一周我一直在反对这个问题.

old*_*mer 4

假设我理解这个问题,也许这会让你开始。相对跳跃是基于电脑的。

d: eb 04 jmp 13 

0xEB 是基于 8 位立即数的相对跳转的操作码。指令的地址位于 objdump 输出中,在本例中为 d 或 0xD。它是一个两字节指令(x86 是可变长度)。它会在输出中告诉您目标地址是什么,在本例中为 jmp 13。因此,在 objdump 输出中查找以 13 和冒号开头的行是下一个代码块的开头。

了解该地址是如何计算的。当开始取指令时,pc位于0xD,它需要两个字节,因此当准备执行该指令时,pc位于0xD+2 = 0xF。偏移量为 0x4,因此 0xF+0x4 = 0x13 是目标地址。

20:75 ed jne f

向后也是如此。pc 加字节数 = 0x20+2 = 0x22。0xED 是一个有符号数,并且是负数,因此无论您的地址寄存器有多大,都会将 0xED 符号扩展为 0xFFFFFFF...FFFFED。添加 0x22+0xFFFFFF...FFFED,您将得到目标地址 0x0F。您还可以将 0xED 取反并加 1 以将其取反。~0xED = 0x12,0x12+1 = 0x13。所以0xED意味着减去0x13。0x22-0x13=0x0F。

这里还有更多,在每种情况下它都会为您提供目标地址,您可以在 objdump 输出中查找该地址。

了解它如何计算该值。同样的情况,从 0x400A81 处的操作码开始,在这种情况下,可变长度指令需要 6 个字节。因此,当您准备好执行时,pc 位于 0x400A81+6 = 0x400A87。偏移量为 0x107,因此如果满足条件,目标地址为 0x400A87 + 0x107 = 0x400B8E。

请注意,这些是从较大的程序中提取出来的,而不是顺序代码,只是一组孤立的示例。

  400a81: 0f 8f 07 01 00 00 jg 400b8e
  400a8f: 0f 8f e6 00 00 00 jg 400b7b
  400a9d: 0f 8f c5 00 00 00 jg 400b68
  400aab: 0f 8f a4 00 00 00 jg 400b55
  400ab9: 0f 8f 83 00 00 00 jg 400b42
  401d76: 0f 8f 31 01 00 00 jg 401ead