0

Consider the C code below:

#include <stdio.h>

void greet(void){
    printf("Hello!\n");
}

int main (){
    greet();
    return 0;
}

I compiled it with gcc to a 64-bit ELF called hello.

Then in my first experiment, I disassembled (decoded) the whole .text section using XED as follows:

./xed -i hello

I am interested in the function call to greet, which was disassembled as follows:

XDIS 1168: CALL    BASE    E8DCFFFFFF     call 0x1149 <greet>

So far it looks fine since 0x1149 is truly the entry to the greet function.

But supposing that the string "E8DCFFFFFF" is the equivalent hex instruction, the confusion arises: in a second experiment with XED, I decided to disassemble only the function call instruction, i.e. the hex string "E8DCFFFFFF", as follows:

./xed -d E8DCFFFFFF

and here is the result:

ICLASS:     CALL_NEAR
CATEGORY:   CALL
EXTENSION:  BASE
IFORM:      CALL_NEAR_RELBRz
ISA_SET:    I86
ATTRIBUTES: FIXED_BASE0 MPX_PREFIX_ABLE SCALABLE STACKPUSH0 
SHORT:      call 0xffffffe1

I was expecting call 0x1149 but I got call 0xffffffe1. Can anybody explain it please?

jps
  • 20,041
  • 15
  • 75
  • 79
Farzam
  • 131
  • 2
  • 13
  • 2
    **The operand is relative** -- notice iform CALL_NEAR_RELBRz says REL. (1168+5)+(-24) is 1149 but (0+5)+(-24) is -1f. Dupe https://stackoverflow.com/questions/10376787/need-help-understanding-e8-asm-call-instruction-x86 https://stackoverflow.com/questions/65926175/why-does-e8-f2-ff-ff-ff-translate-to-call-0xfffffff7 also see https://stackoverflow.com/questions/44882315/how-does-the-cpu-distinguish-call-rel16-e8-cw-and-call-rel32-e8-cd . – dave_thompson_085 Jul 05 '22 at 08:39
  • 1
    Thanks a lot! So we can note that in the actual instruction **E8DCFFFFFF**, the 32-bit signed offset **FFFFFFDC** = -0x24 is relative to the address of the next instruction after CALL (here 0x1168 + 5), but in the decoded XED result, the 32-bit signed offset **FFFFFFE1** = -0x1F is relative to the address of the CALL instruction itself. Do you have any idea why XED does this? I mean why it doesn't decode **E8DCFFFFFF** to **CALL 0xFFFFFFDC**? – Farzam Jul 06 '22 at 00:22
  • 1
    @dave_thompson_085 I forgot to mention you in my previous comment. – Farzam Jul 06 '22 at 17:09
  • 1
    I don't speak for Intel, but my guess would be they think that people who disassemble a program would like to see instantly where a call (or jump etc) goes rather than have to do manual arithmetic every time. Decades ago I debugged code on PDP-11 (more exactly LSI-11/2 and /23) using console ODT and I probably spent weeks of my life adding offsets that the computer could have done in a fraction of a second. – dave_thompson_085 Jul 07 '22 at 10:38
  • 1
    @dave_thompson_085 Thanks a lot for you informative comments! – Farzam Jul 07 '22 at 19:58

0 Answers0