【问题标题】:Differencing the instruction of the same opcode区分同一操作码的指令
【发布时间】:2015-09-17 00:06:24
【问题描述】:

出于学习目的,我正在 Linux(64 位)上编写 ftrace 程序,我需要使用 ptrace() syscall 解析指令。

我感兴趣的指令是 ret 和 call。调用指令可能采用不同的操作码(0xe8、0x9a 和 0xff)。这是最后一个问我的问题:这个 0xff 也可以代表 inc、dec、jmp 和 push 指令,但我读到“寄存器/操作码字段”发生了变化。

我的问题是:如何获得 call 被调用而不是 dec 或 inc 的信息?我可以访问操作码和寄存器。

感谢您阅读和帮助我。

【问题讨论】:

    标签: assembly x86 machine-code


    【解决方案1】:

    您可以通过查看下一个指令字节中的 3 位字段(位 5、4、3)来区分。

    000     inc instruction
    
    001     dec instruction
    
    010     intra-segment indirect call
    
    011     inter-segment indirect call
    
    100     intra-segment indirect jump
    
    101     inter-segment indirect jump
    
    110     push instruction
    
    111     unused
    

    【讨论】:

    • 那么如果下一个指令字节是 0001 1000,那么位 (5,4,3) 将是 110,这意味着我们处理的是推送指令吗?如果有人知道答案,我会有另一个问题:为什么在解析调用(0xff / 0xe8 / 0x9a)和 ret(0xc3、0xc2、0xca、0xcb)操作码的可执行文件中调用和 ret 的数量不同?是我的错误还是我缺少信息?
    • 如果下一个指令字节是0001 1000,则位(5,4,3)将是011.
    • 您评论的问题:如果对一个函数有 3 次调用,则代码(可能)包含 3 次调用和 2 次调用 - 一个来自函数,一个来自主函数 - 或不。 main 可能以系统调用结束。
    • 我真的不能说,因为你问的是不同的问题。 8086的指令是变长的,所以只找0xFF字节是没有用的,需要完全反汇编才能找到每个指令字节序列的第一个字节。
    • 他说在另一条指令的中间可能有一个0xFF,所以你不能仅仅为了那个而扫描一个insn流。但是,如果您以单步方式使用ptrace 并为您在insn 边界处停止,那么这种方法应该可以工作。您没有详细说明您的测试是如何工作的,我们无法说明这些数字是否适合 libc 启动。不过我会相信的;现代 glibc 和共享库在启动时做了很多事情。许多 call/ret 对可能是非常小的函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2018-07-28
    相关资源
    最近更新 更多