x86 asm中调用指令的编码有什么区别?

时间:2016-08-07 02:50:03

标签: visual-c++ assembly x86 inline-assembly

供参考:英特尔call instruction文档的HTML摘录。

我知道第3.1.1.3节解释了这一点,但我无法理解本手册,可能是因为它过于技术化了。

  1. /2/3内的FF /2FF /3是什么?

  2. r/m32m16:32之间有什么区别? r/m32涵盖了32位寄存器和内存操作数,因此不会使m16:32冗余吗?

  3. 根据手册call ptr16:32是“在操作数中给出的远程,绝对,地址”。如果我理解正确,这将允许我在给定的绝对32位地址处调用函数。如何在绝对地址0x717A60调用该函数(我在MSVC中使用内联汇编程序)? call 0x717A60给了我一个错误,call ds:0x717A60已汇总到call [0x717A60]

  4. 以下机器代码对应哪个操作码? FF 15 90 98 76 70

1 个答案:

答案 0 :(得分:2)

  1. /2/3的对比:请参阅指令摘要表中的 3.1.1.1O操作码列

      

    / digit - 0到7之间的数字表示指令的ModR / M字节仅使用r / m(寄存器)   或内存)操作数。 reg字段包含为指令的操作码提供扩展的数字。

    使用单操作数指令的mod / rm字节的/r字段与inc r/m32FF /0)等指令相同。

    x86以这种方式使用多个单操作数指令重载一些操作码字节。 3位/r字段变为另外3个操作码位而不是操作数。

  2. r/m32m16:32对比ptr16:32

    另见x86 function call types

    A"远" call加载CS段注册以及IP / EIP / RIP。正常"近" call只需要一个32位(或64位)地址,并且不会修改CS

    far call从未用于"正常"普通操作系统上的32或64位用户空间代码,因为它们都使用平面内存模型。

    ptr16:32是立即数,16位段值和32位绝对地址编码到指令中(小端,首先是32位偏移,然后是新的CS值)。 这是far call 。见this Q&A。汇编器将为far call some_symbol生成此指令编码,并定义段some_symbol中的段值。再次,您实际上不太可能在16位代码之外使用此值。但如果你这样做,请参阅this Q&A for how to get MASM to emit it

    m16:32是一个6字节的内存操作数,从ModR / M字节编码的有效地址加载。 这是另一个远程电话。因此call far [eax]eax中的地址进行48位加载。只有存储器寻址模式对于ModR / M字节是合法的,因为该指令需要的数据多于寄存器的宽度。 (即call far eax不合法)

    r/m32 是近距离通话的内存或注册操作数您可以从call eaxcall [eax]获取此信息。当然,任何寻址模式都是合法的,例如call FS:[edi + esi*4 + some_table]。 FS段覆盖前缀适用于加载函数指针的位置,而不是它跳转到的段。 (即它不会改变CS,因为它仍然是近距离呼叫。)

      

    如何在绝对地址0x717A60

    处调用该函数

    Call an absolute pointer in x86 machine code

    如果您的代码不必与位置无关,那么到目前为止,最好的选择是组装到call rel32并使用正确的相对位移来到达该地址。在NASM和AT& T语法中,您可以简单地编写call 0x717A60并且汇编程序+链接器负责处理它。我不确定如何在MASM中写它; MSVC内联asm不接受call 123456h

    没有绝对直接接近call编码,所以如果您确实需要PIC,那么您应该执行类似mov eax, 0x717A60 / call eax的操作。

    您不想使用call far绝对直接呼叫,因为它可能更慢,并且推送CS:EIP而不仅仅是EIP作为退货地址。您还必须知道要在细分字段中放入什么内容。

      

    FF 15 90 98 76 70

    反汇编为call DWORD PTR ds:0x70769890(在GNU objdump -Mintel语法中),这是call r/m32,其中操作数是[disp32]绝对寻址模式。

    (或者在64位代码中,它是与rel32相关的RIP相对寻址模式,但仍然是从静态位置加载函数指针的内存间接call 。)

    另请参阅代码wiki以获取更多文档链接。