供参考:call指令的英特尔文档的HTML摘录。
我知道第3.1.1.3节对此进行了解释,但是我在理解手册时遇到了麻烦,可能是因为它太技术性了。
FF /2和FF /3中的/2和/3是什么?
r/m32和m16:32有什么区别? r/m32涵盖了32位寄存器和内存操作数,所以这不会使m16:32冗余吗?
根据手册,call ptr16:32是"调用操作数中给出的绝对绝对地址"。 如果我理解正确,这将允许我在给定的绝对32位地址处调用函数。 如何在绝对地址0x717A60处调用函数(我在MSVC中使用内联汇编器)? call 0x717A60给我一个错误,并且call ds:0x717A60被组装到call [0x717A60]。
以下机器代码对应于哪个操作码? FF 15 90 98 76 70
-
@rcgldr:它不使用段寄存器,它是一个加载CS的far call。 你不想要那个。
-
C ++如何参与其中?
-
@DavidHoelzer:有一个问题涉及使用作为项目3一部分掩埋的msvc嵌入式asm生成一个call到绝对地址,直到我写完对问题明显部分的答案后,我才注意到。 这是一个很好的例子,说明了为什么SO在每个Question-post指南中都有一个问题。
-
x86函数调用类型几乎重复,但是我不确定哪一个应该作为另一个的重复关闭。
-
第一部分是FF / 4中/ 4表示什么的重复项?
/2 vs. /3:请参见指令摘要表中的第3.1.1.1O节"操作码"列:
/digit — A digit between 0 and 7 indicates that the ModR/M byte of the instruction uses only the r/m (register
or memory) operand. The reg field contains the digit that provides an extension to the instruction's opcode.
在这里使用单操作数指令的mod / rm字节的/r字段与inc r/m32(FF /0)之类的指令相同。
x86以这种方式用多个单操作数指令重载了一些操作码字节。 3位/r字段变为另外3个操作码位,而不是操作数。关于此的更多细节:
-
如何阅读英特尔操作码表示法
-
/ 4在FF / 4中是什么意思?
-
x64指令编码和ModRM字节-有关modrm字节中字段的详细信息。
r/m32与
m16:32与
ptr16:32
另请参见x86函数调用类型
"远" call装入CS段寄存器以及IP / EIP / RIP。普通的" near"调用仅需要一个32位(或64位)地址,而不修改CS。
far call从未在普通OS的"普通" 32或64位用户空间代码中使用,因为它们都使用平面内存模型。
ptr16:32是立即数,具有16位段值和32位绝对地址编码到指令中(小尾数,先偏移32位,然后是新的CS值)。这是far call。请参阅此问答。汇编器将为far call some_symbol生成此指令编码,并从其中定义段some_symbol中获取段值。同样,您实际上不太可能在16位代码之外使用此代码。但是,如果您这样做,请参阅此问答以获取如何使MASM发出它的信息。
m16:32是一个6字节的内存操作数,从ModR / M字节编码的有效地址加载。这是另一个遥不可及的地方。因此call far [eax]从eax中的地址进行48位加载。对于ModR / M字节,只有存储器寻址模式才是合法的,因为该指令需要的数据要多于寄存器的宽度。 (即call far eax不合法)
r/m32是用于Near调用的内存或寄存器操作数。您是从call eax或call [eax]获得的。当然,任何寻址方式都是合法的,例如call FS:[edi + esi*4 + some_table]。 FS segment-override前缀适用于函数指针从中加载的位置,而不是其跳转到的段。 (即,它不会更改CS,因为它仍然是临近通话。)
How can I call the function at the absolute address 0x717A60
请参阅在x86机器代码中调用绝对指针。
如果您的代码不必与位置无关,那么到目前为止,最好的选择是将其组装到call rel32并以正确的相对位移到达该地址。使用NASM和AT&T语法,您只需编写call 0x717A60,然后由汇编程序+链接程序进行处理。我不确定如何用MASM编写它; MSVC内联汇编不接受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。)
另请参阅x86标签Wiki,以获取更多指向文档的链接。