4

I compiled the following program on a 64-bit linux machine:

#include <stdio.h>

main()
{
    int a = 12345;

    if (a == 12346)
        printf ("YES\n");

    return;
}

If I output the binary file using hexdump, I can find the 12346 (which is 303a in hex), but not the 12345 value (0x3039). Why is that?

(little or big endian should make no difference in finding that value)

Matt
  • 165
  • 2
  • 8
  • 2
    Why does little-vs-big make no difference? – Thilo Feb 13 '17 at 11:01
  • I would expect the compiler to be able to optimize the comparison all away. Are you sure the `0x303a` you find is the actual number from the source file and not some other sequence of two bytes that happens to just be the same? – Some programmer dude Feb 13 '17 at 11:02
  • 6
    If I do what you've described and compile with `gcc main.c`, I see `39 30` at offset 00000538, just a few bytes prior to the `3A 30`. If I use `gcc -O2 main.c` (e.g., turn on optimizations), I don't see either of them (unsurprisingly, since the whole thing ends up being `return`). – T.J. Crowder Feb 13 '17 at 11:02
  • 1
    Your program is ill-formed. Any modern C compiler would have told you that. – StoryTeller - Unslander Monica Feb 13 '17 at 11:02
  • 1
    Look at the [generated assembly code](https://godbolt.org/g/N56DsA). You should find both numbers if the code is not optimized. – Jabberwocky Feb 13 '17 at 11:03
  • Good chances are, you are finding 12346 by coincidence, and your compiler has optimized out the condition and everything inside it. See if changing it to some other number makes it disappear. – Sergey Kalinichenko Feb 13 '17 at 11:06
  • `return;` isn't a good idea in a function returning `int`. – melpomene Feb 13 '17 at 11:07
  • yes I know the code is not perfect, it's just for the example. And all there is are warnings, not errors. – Matt Feb 13 '17 at 12:03
  • little-vs-big makes no difference because I will have 3039 0000 instead of 0000 3039. So I can still find my 3039 inside. – Matt Feb 13 '17 at 12:04
  • ... except that it's `39 30 00 00` vs `00 00 30 39` – Thilo Feb 13 '17 at 12:44

2 Answers2

6

Here’s where the values are in the output of plain hexdump for me; look at the bolded areas.

0000500 39fc 0030 8100 fc7d 303a 0000 0a75 a4bf

If you were expecting to see 3039 as one group, that would explain the confusion. The actual bytes are:

fc 39 30 00 00 81 7d fc 3a 30 00 00 75 0a bf a4

If you don’t want hexdump to do its “helpful” default output where it reinterprets the input as a sequence of little-endian two-byte words, you could spend an hour figuring out how to use its format strings or just pick xxd instead.

Ry-
  • 218,210
  • 55
  • 464
  • 476
4

The easiest way to answer this sort of question is to compile it with the -S command line option, which outputs your C program as assembly code.

This is what your main() function compiles to without any optimization (i.e., with the -O0 command line switch). I've removed some redundant marker statements and added a few comments:

main:
        leal    4(%esp), %ecx        # Create local storage on stack
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $20, %esp
        movl    $12345, -12(%ebp)   # Initialize `a` to 12345
        cmpl    $12346, -12(%ebp)   # Compare with 12346
        jne     .L4
        subl    $12, %esp           # If equal, ...
        pushl   $.LC0
        call    puts                # print "YES"
        addl    $16, %esp
.L4:
        nop
        nop
        movl    -4(%ebp), %ecx      # Tidy up and exit
        leave
        leal    -4(%ecx), %esp
        ret

You can see that the numbers 12345 and 12346 are included in your code at the movl and cmpl instructions.

With optimization, the code becomes a lot simpler. The compiler can see that the if statement never evaluates to true. It can also see that the variable a is never used. This is what main() looks like when compiled with hard optimization (-O3):

main:
        rep ret

(Note: I compiled this on 32-bit Ubuntu Xenial, but exactly the same optimizations would occur on a 64-bit machine.)

r3mainer
  • 23,981
  • 3
  • 51
  • 88