assembly - 使用 objdump 时确定寄存器值

标签 assembly x86 x86-64 control-flow objdump

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

最佳答案

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

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 编辑 jne f

倒退也一样。 pc 加上字节数 = 0x20+2 = 0x22。 0xED 是一个有符号数并且是负数,所以符号将 0xED 扩展到 0xFFFFFFFF...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

关于assembly - 使用 objdump 时确定寄存器值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4310286/

相关文章:

python - 返回值中的 CTypes 错误

gcc - 用 gcc 清理 x86_64 汇编输出?

assembly - 在 c/asm x86 中重新编程中断

GCC跳转表初始化代码生成movsxd并添加?

c - 使用您自己的页面错误处理程序

linux - NASM Linux x64 |将二进制编码为base64

gcc - 臂组件: '#define' risk

编译包含包含 C 定义的头文件的汇编代码

c - 参数在 gdb 中的哪里以及 ret 在哪里?

自定义内核不读取全局变量和 char*