x86函数调用类型

Iva*_*ars 1 x86 assembly call instruction-set

我是x86的新手.我的问题是关于函数调用.据我所知,有三种函数调用类型:短调用(0xe8),远调用(0x9a)和近调用(0x ??).有些呼叫短呼叫一个相对呼叫(ip + = arg/cs = inv)并远远调用绝对呼叫(ip = arg/cs = arg),但接近呼叫(ip =?/ cs =?)怎么样.有人说在32位系统上调用函数far(9a)几乎肯定是错误的.为什么?x86不代表32位系统吗?far call的参数是一个扁平的地址(我们在c ++或其他语言中使用的那个)或cs:ip notated以及如何将普通地址转换为cs:ip form?还有其他函数调用类型吗?

int*_*jay 7

CALL教学类型是:

  • 近,相对(操作码E8)(call func)
  • 远,绝对(操作码9A)(call 0x12:0x12345678)
  • 近,绝对,间接(操作码FF/2)(call [edi])
  • 远,绝对,间接(操作码FF/3)(call far [edi])

远程调用意味着它除了更改段选择器(cs)的值eip.近呼叫仅改变ip/ eip/ rip.

相对意味着地址将相对于下一条指令的地址,而绝对调用则提供跳转到的确切地址.

间接调用指定寄存器或存储器内容中的目标地址,而在直接调用中,它将被指定为指令的一部分.

有人说在32位系统上调用函数far(9a)几乎肯定是错误的.为什么?

可能是因为一般32位操作系统将使用平面内存模型,其中所有内存都可以从同一段访问(如果允许访问),因此无需更改值cs.

Far call还推动CS:EIP而不仅仅是EIP作为返回地址,如果你调用一个正常的函数来预期在返回地址正上方找到堆栈参数,这就是一个问题.

x86不代表32位系统吗?

编号x86最初是一个16位指令集,后来扩展到32位然后扩展到64位.另请参阅Stack Overflow的x86标记wiki

far call的参数是一个普通的地址(我们在c ++或其他语言中使用的那个)或cs:ip notated以及如何将普通地址转换为cs:ip form?

我不知道你的"普通地址"是什么意思.在具有平坦内存模型的32位操作系统上,存储在C++指针中的地址将不包含段选择器,因此要将其转换为远地址,您需要添加值cs.

但对于绝对直接的形式,你需要cs在建立时间的正确价值.