x86 asm中的调用指令的编码之间有什么区别? [英] What is the difference between the encodings for the call instruction in x86 asm?

查看:165
本文介绍了x86 asm中的调用指令的编码之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

供参考: call指令的英特尔文档的HTML摘录.

For reference: an HTML extract of Intel's documentation for the call instruction.

我知道第3.1.1.3节对此进行了解释,但是我在理解手册时遇到了麻烦,可能是因为它太技术性了.

I am aware that section 3.1.1.3 explains this but I am having trouble understanding the manual, probably because it is too technical.

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

r/m32m16:32有什么区别? r/m32涵盖了32位寄存器和内存操作数,所以这不会使m16:32变得多余吗?

What is the difference between r/m32 and m16:32? r/m32 covers both 32-bit registers and memory operands so wouldn't that make m16:32 redundant?

根据手册call ptr16:32是调用操作数中给出的绝对绝对地址".如果我理解正确,这将允许我在给定的绝对32位地址处调用函数.如何在绝对地址0x717A60处调用函数(我在MSVC中使用内联汇编器)? call 0x717A60给我一个错误,并且call ds:0x717A60被组装到call [0x717A60].

According to the manual call ptr16:32 is a "Call far, absolute, address given in operand". If I understood correctly, this will allow me to call a function at a given absolute 32-bit address. How can I call the function at the absolute address 0x717A60 (I'm using the inline assembler in MSVC)? call 0x717A60 gives me an error and call ds:0x717A60 is assembled to call [0x717A60].

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

Which opcode does the following machine code correspond to? FF 15 90 98 76 70

推荐答案

  1. /2/3:请参见指令摘要表中的第3.1.1.1O节操作码"列:
  1. The /2 vs. /3: See Section 3.1.1.1O Opcode Column in the Instruction Summary Table:

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

/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)之类的指令相同.

Using the /r field of the mod/rm byte of one-operand instructions is the same here as for instructions like inc r/m32 (FF /0).

x86以这种方式用多个单操作数指令重载了一些操作码字节. 3位的/r字段变为另外3个操作码位,而不是操作数.对此有更多详细信息:

x86 overloads a few opcode bytes with multiple one-operand instructions this way. The 3-bit /r field becomes another 3 opcode bits instead of an operand. More detail about that:

  • How to read the Intel Opcode notation
  • What does the /4 mean in FF /4?
  • x64 instruction encoding and the ModRM byte - details about the fields in the modrm byte.

另请参见 x86函数调用类型

远"一个call装入CS段寄存器以及IP/EIP/RIP.正常的靠近"呼叫仅需要一个32位(或64位)地址,并且不会修改CS.

A "far" call loads the CS segment register as well as IP/EIP/RIP. A normal "near" call only needs a 32-bit (or 64-bit) address, and doesn't modify CS.

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

far call is never used in "normal" 32 or 64-bit user-space code on normal OSes, because they all use a flat memory model.

ptr16:32是立即数,具有16位段值和32位绝对地址编码到指令中(小尾数,先偏移32位,然后是新的CS值). 这是far call .请参阅此问题与解答.汇编程序将为far call some_symbol生成此指令编码,并从段some_symbol中定义段中获取段值.同样,您实际上不太可能在16位代码之外使用此代码.但是,如果您这样做,请参阅此问题与解答有关如何使MASM发出的信息.

ptr16:32 is an immediate, with the 16-bit segment value and the 32-bit absolute address encoded into the instruction (little-endian, with the 32-bit offset first then the new CS value). This is a far call. See this Q&A. Assemblers will generate this instruction encoding for far call some_symbol, taking the segment value from the segment some_symbol is defined in. Again, you're really unlikely to ever use this outside of 16-bit code. But if you do, see 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不合法)

m16:32 is a 6-byte memory operand, loaded from the effective address encoded by the ModR/M byte. This is another far call. So call far [eax] does a 48-bit load from the address in eax. Only memory addressing modes are legal for the ModR/M byte, because the instruction needs more data than the width of a register. (i.e. call far eax isn't legal)

r/m32 是用于近距离呼叫的内存或寄存器操作数.您可以从call eaxcall [eax]中获得它.当然,任何寻址方式都是合法的,例如call FS:[edi + esi*4 + some_table]. FS segment-override前缀适用于函数指针从中加载的位置,而不是其跳转到的段. (即,它不会更改CS,因为它仍然是近距离通话.)

r/m32 is a memory or register operand for a near call. You get this from call eax or call [eax]. Of course any addressing mode is legal, e.g. call FS:[edi + esi*4 + some_table]. The FS segment-override prefix applies to the location the function pointer is loaded from, not the segment that it jumps to. (i.e. it doesn't change CS because it's still a near call.)

如何在绝对地址0x717A60处调用该函数

How can I call the function at the absolute address 0x717A60

请参见在x86机器代码中调用绝对指针

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

If your code doesn't have to be position-independent, by far the best choice is something that assembles to call rel32 with the right relative displacement to reach that address. In NASM and AT&T syntax, you can simply write call 0x717A60 and the assembler + linker take care of it. I'm not sure how to write it in MASM; MSVC inline asm doesn't accept call 123456h.

call编码附近没有绝对直接的编码,因此,如果您确实需要PIC,则应该执行类似mov eax, 0x717A60/call eax的操作.

There is no absolute direct near call encoding, so if you do need PIC then you should do something like mov eax, 0x717A60 / call eax.

您不想使用call far绝对直接调用,因为它可能慢得多,并且将CS:EIP而不只是EIP作为返回地址.您还必须知道要在细分字段中输入什么.

You don't want to use a call far absolute direct call, because it's probably much slower, and pushes CS:EIP instead of just EIP as the return address. You'd also have to know what to put in the segment field.

FF 15 90 98 76 70

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

That disassembles to call DWORD PTR ds:0x70769890 (in GNU objdump -Mintel syntax), which is a call r/m32, where the operand is a [disp32] absolute addressing mode.

(或者在64位代码中,它是具有rel32的RIP相对寻址模式,但仍然是从内存中静态位置加载功能指针的内存间接call.)

(Or in 64-bit code, it's a RIP-relative addressing mode with that rel32, but still a memory-indirect call that loads a function-pointer from a static location.)

另请参见标签Wiki的问题,以了解更多信息链接到文档.

See also the x86 tag wiki for more links to docs.

这篇关于x86 asm中的调用指令的编码之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆