Following is the output of objdump of a sample program,
080483b4 <display>: 80483b4: 55 push %ebp 80483b5: 89 e5 mov %esp,%ebp 80483b7: 83 ec 18 sub $0x18,%esp 80483ba: 8b 45 0c mov 0xc(%ebp),%eax 80483bd: 89 44 24 04 mov %eax,0x4(%esp) 80483c1: 8d 45 fe lea 0xfffffffe(%ebp),%eax 80483c4: 89 04 24 mov %eax,(%esp) 80483c7: e8 ec fe ff ff call 80482b8 <strcpy@plt> 80483cc: 8b 45 08 mov 0x8(%ebp),%eax 80483cf: 89 44 24 04 mov %eax,0x4(%esp) 80483d3: c7 04 24 f0 84 04 08 movl $0x80484f0,(%esp) 80483da: e8 e9 fe ff ff call 80482c8 <printf@plt> 80483df: c9 leave 80483e0: c3 ret 080483e1 <main>: 80483e1: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483e5: 83 e4 f0 and $0xfffffff0,%esp 80483e8: ff 71 fc pushl 0xfffffffc(%ecx) 80483eb: 55 push %ebp 80483ec: 89 e5 mov %esp,%ebp 80483ee: 51 push %ecx 80483ef: 83 ec 24 sub $0x24,%esp 80483f2: c7 44 24 04 f3 84 04 movl $0x80484f3,0x4(%esp) 80483f9: 08 80483fa: c7 04 24 0a 00 00 00 movl $0xa,(%esp) 8048401: e8 ae ff ff ff call 80483b4 <display> 8048406: b8 00 00 00 00 mov $0x0,%eax 804840b: 83 c4 24 add $0x24,%esp 804840e: 59 pop %ecx 804840f: 5d pop %ebp 8048410: 8d 61 fc lea 0xfffffffc(%ecx),%esp
What i need to understand, is in main we see the following at address - 8048401, call 80483b4 , however the machine code is - e8 ae ff ff ff. I see that CALL instruction is E8 but how is the address of function 80483b4 getting decoded to FFFFFFAE? I did a lot of search in google but it did not return anything. Can Anyone please explain?
E8 is the operand for "Call Relative", meaning the destination address is computed by adding the operand to the address of the next instruction. The operand is 0xFFFFFFAE, which is negative 0x52. 0x808406 - 0x52 is 0x80483b4.
Most disassemblers helpfully calculate the actual target address rather than just give you the relative address in the operand.
Interesting question. I've had a look at Intel's documentation and the
E8 opcode is
CALL rel16/32. 0xffffffae is actually a 32-bit two's complement signed integer equal to -82 decimal; it is a relative address from the byte immediately after the opcode and its operands.
If you do the math you can see it checks out:
0x8048406 - 82 = 0x80483b4
This puts the instruction pointer at the beginning of the
Near calls are typically IP-relative -- meaning, the "address" is actually an offset from the instruction pointer. In such case, EIP points to the next instruction (so its value is
-00000052 in two's complement) to it, and you get
Note that all this math is 32-bit. You're not doing any 64-bit operations here (or your registers would have
Rs instead of
Es in their names, and the addresses would be much longer).
User contributions licensed under CC BY-SA 3.0