Question

I'm new in x86. My question is about function calls. As far as i know there is three function call types: short call (0xe8), far call (0x9a) and near call (0x??). Some call short call a relative call (ip += arg / cs = inv) and far call an absolute call (ip = arg / cs = arg), but what about near call (ip = ? / cs = ?). Some say that calling function far (9a) is almost certainly wrong on 32-bit systems. Why? Doesn't x86 mean 32-bit system? Is far call's argument a flat address (the one we use in c++ or other languages) or cs:ip notated and how do i convert a plain address into cs:ip form? Is there other function call types?

Was it helpful?

Solution

The types of CALL instruction are:

  • Near, relative (opcode E8) (call func)
  • Far, absolute (opcode 9A) (call 0x12:0x12345678)
  • Near, absolute, indirect (opcode FF /2) (call [edi])
  • Far, absolute, indirect (opcode FF /3) (call far [edi])

Far call means that it changes the value of the segment selector (cs) in addition to eip. Near call changes only ip/eip/rip.

Relative means that the address will be relative to the address of the next instruction while an absolute call gives the exact address to jump to.

An indirect call specifies the target address in a register or memory contents, while in a direct call it will be specified as part of the instruction.

Some say that calling function far (9a) is almost certainly wrong on 32-bit systems. Why?

Probably because generally 32-bit operating systems will use a flat memory model where all memory can be accessed from the same segment (if access is permitted), so there is no need to change the value of cs.

Far call also pushes CS:EIP instead of just EIP as the return address, which is a problem if you call a normal function that's expecting to find stack args right above the return address.

Doesn't x86 mean 32-bit system?

No. x86 was originally a 16-bit instruction set, and was later extended to 32 bits and then 64 bits. See also Stack Overflow's x86 tag wiki

Is far call's argument a plain address (the one we use in c++ or other languages) or cs:ip notated and how do i convert a plain address into cs:ip form?

I don't know what you mean by a "plain address". On a 32 bit OS with flat memory model the address stored in a C++ pointer will not include a segment selector, so to convert it to a far address you'd add the value of cs.

But for the absolute direct form, you need the right value of cs at built time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top