0

For this particular c code.

#include <stdio.h>
int main()
{
     int *p = (int *)20;
     int *q = (int *)30;
     printf("%d", q-p);
}

This is the dump of gdb disass /m main

Dump of assembler code for function main:
   0x0000000100000f45 <+0>:    push   %rbp // save the current base pointer
   0x0000000100000f46 <+1>:    mov    %rsp,%rbp // base pointer reference the highest stack entry
   0x0000000100000f49 <+4>:    sub    $0x10,%rsp // Move stack pointer 0x10/4 = (4) memory entries downwards 
   0x0000000100000f4d <+8>:    movq   $0x14,-0x8(%rbp) // save (0x14 = 20), 0x8/4 mem address lower than base pointer ref ( 'q' for quad word )
   0x0000000100000f55 <+16>:    movq   $0x1e,-0x10(%rbp) // save (0x14 = 30), 0x10/4 mem address lower than base pointer ref
   0x0000000100000f5d <+24>:    mov    -0x10(%rbp),%rdx  // Save  0x10/4 memory addresses lower than the base pointer is referencing to rdx 
   0x0000000100000f61 <+28>:    mov    -0x8(%rbp),%rax // Save  0x8/4 memory addresses lower than the base pointer is referencing to rax
   0x0000000100000f65 <+32>:    sub    %rax,%rdx // subtract rdx from rax and result in rax
   0x0000000100000f68 <+35>:    mov    %rdx,%rax // move value of rax to rdx
   0x0000000100000f6b <+38>:    sar    $0x2,%rax // shift right 2 ( divide the value of rax by 4 )
   0x0000000100000f6f <+42>:    mov    %rax,%rsi // ( move value of rsi to rax )
   0x0000000100000f72 <+45>:    lea    0x31(%rip),%rdi        # 0x100000faa
   0x0000000100000f79 <+52>:    mov    $0x0,%eax
   0x0000000100000f7e <+57>:    callq  0x100000f8a
   0x0000000100000f83 <+62>:    mov    $0x0,%eax
   0x0000000100000f88 <+67>:    leaveq
   0x0000000100000f89 <+68>:    retq
End of assembler dump.

I tried and from searching and understanding I have commented each step. But after this I don't know how this program in actually running.

Please help.

EDIT. After -O2 I get this.

Dump of assembler code for function main:
   0x0000000100000f70 <+0>: sub    $0x8,%rsp
   0x0000000100000f74 <+4>: mov    $0x2,%esi
   0x0000000100000f79 <+9>: xor    %eax,%eax
   0x0000000100000f7b <+11>:    lea    0x2c(%rip),%rdi        # 0x100000fae
   0x0000000100000f82 <+18>:    callq  0x100000f8e
   0x0000000100000f87 <+23>:    xor    %eax,%eax
   0x0000000100000f89 <+25>:    add    $0x8,%rsp
   0x0000000100000f8d <+29>:    retq
End of assembler dump.
  • Pointer arithmetic with pointers to different objects is undefined?? If the pointers were to the same object their difference would be the *number of elements* of separation (not necessarily bytes). – Weather Vane Jul 14 '17 at 18:32
  • @WeatherVane yes, you're right! The output is `2` which is basically `(30-20)/4 = 2` as an `int` occupies for `4 bytes`. But I wanted to know how it's been executing at assembly level. – therewasaduck Jul 14 '17 at 18:33
  • And what would you expect if the objects were allocated the other way round, which they could be? You are asking how *undefined behaviour* works which is futile. – Weather Vane Jul 14 '17 at 18:34
  • shifting by 2 divides by 2^2=4. Fixed. – ikegami Jul 14 '17 at 18:35
  • @WeatherVane it's just curiosity that is making me want to understand how `2` is the output and relation between `q` and `p`. I thought looking at `assembly` would make it clear. – therewasaduck Jul 14 '17 at 18:38
  • There is no relation between `2` and the value of `q` and `p`. You could just as easily have gotten `3` or a segfault. – ikegami Jul 14 '17 at 18:39
  • Please read [this answer](https://stackoverflow.com/a/28649337/4142924). – Weather Vane Jul 14 '17 at 18:40
  • @ikegami I believed so but I tried with other values. `p = 200` and `q=300` returns `25` which supports the fact that the difference would be the number of elements of separation. – therewasaduck Jul 14 '17 at 18:41
  • The disassembly is noisy, confusing, and pointless because it is for *unoptimized* code. If only I had a dollar for each time someone on SO asked a question about the assembly language representation of unoptimized C code… Flip the `-O2` switch and try again. – Cody Gray - on strike Jul 14 '17 at 18:41
  • No, not always. The different is definitely not always the "number of elements of separation". That's only the case when both pointers point to elements of the same array object, or one past the last element of the array object. – ikegami Jul 14 '17 at 18:41
  • Thank you all but it would be nice to have an understanding of why the implementation would report that p - q is 2 . (It can do anything. But we can still wonder about why it does do what it does.) – therewasaduck Jul 14 '17 at 18:44
  • 1
    The only time IMO when exploring UB is worth doing is to satisfy myself that a bug did cause some side-effect which did not appear to be related, and wasn't caused by another undiscovered bug. – Weather Vane Jul 14 '17 at 18:47
  • And that is so much clearer. Now it's obviously using 2 as the result. Which brings you immediately to consulting the C language standard for an explanation of why. Turns out it's undefined behavior: [C pointer arithmetic](https://stackoverflow.com/questions/2117486/c-pointer-arithmetic). Case closed. – Cody Gray - on strike Jul 14 '17 at 18:52
  • @CodyGray but how in assembly? If you could explain me each step of the assembly it would be much clearer. – therewasaduck Jul 14 '17 at 18:55
  • I don't understand what you're asking. It moves 2 into the `esi` register, which is how the corresponding argument is passed to the `printf` function, according to the calling convention (presumably System V AMD64). If your question is *why* does it do this, the answer is undefined because the input code is invalid. It could do just about anything. Be glad it didn't make [demons fly out your nose](http://catb.org/jargon/html/N/nasal-demons.html); that's much messier. – Cody Gray - on strike Jul 14 '17 at 18:57
  • 1
    Do you mean why is it 2 instead of 2.5? Probably because integer division rounds down. – dbush Jul 14 '17 at 19:02
  • @CodyGray Yes, I was interested in _why_ it does that but I understood that for any reason and for no reason. There isn't an answer for it. It's not necessary that it will move 2 or something else. Also, +1 for demons out of nose. Thank you. – therewasaduck Jul 14 '17 at 19:26

0 Answers0