3

The test platform is on Linux 32bit, x86. So basically I wrote a simple C program like this:

void main()
{
        double a = 10.0;
        printf("hello world %f\n", a);

}

I use gcc to compile to into ELF binary, and use objdump to disassemble it. I solve the reference to .rodata section, and refine the asm code in this :

extern  printf
section .rodata

S_80484d0   db 0x68
db 0x65
  db 0x6c
db 0x6c
db 0x6f
db 0x20
db 0x77
db 0x6f
db 0x72
db 0x6c
db 0x64
db 0x20
db 0x25
db 0x66
db 0x0a


S_80484f0 db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40

section .text
global main
main:
push   ebp
mov    ebp,esp
and    esp,0xfffffff0
sub    esp,0x20
fld    qword [S_80484f0]
fstp   QWORD [esp+0x18]
fld    QWORD [esp+0x18]
fstp   QWORD [esp+0x4] 
mov    DWORD [esp],S_80484d0
call   printf
leave
ret

Then I re-compile this asm code to get a new ELF binary, and comparing the .text section of these two binaries.

Here is the confusing thing: The only different I can find is that there are more leading nop in front of the main function like this:

new ELF binary leading nop:

new ELF binary

new ELF binary ending nop:

new elf binary 2

old ELF binary:

old ELF binary

Basically I don't think it is kinda of "alignment" issue, because there are just too much nop.

What's more, when I change the original code into just a simple helloworld code(without double number a), then basically there is no difference between these two ELF binaries.

Could anyone give me some help on why there are so many nop generated?

Thank you

  • It is alignment. Why would there be a maximum for this? Alignment can be as small or large as a compiler thinks is useful (in your case it seems to dither between 4 and 16 bytes). – usr2564301 Apr 16 '14 at 17:25
  • Try a gcc -S on your original .c file, and you'll get the assembler code the C compiler produces. I bet the the assembler file has some ".align 16" directives in it. – Guntram Blohm supports Monica Apr 17 '14 at 11:46
  • @GuntramBlohm Thank you, yes I tried, but I can only find a “.align 8" at the end of the main function – lllllllllllll Apr 17 '14 at 16:15
8

Alignment.

Note that all of the NOPs end (and the next function begins) at ...C0, ...F0. The compiler and/or linker inserted padding bytes so that the functions begin at 0x10 aligned addresses.

Different compilers / linkers will use different values for these bytes. I've seen 90 (nop), CC (int3), as well as multi-byte NOPs that exactly fill the space between the functions.

You should check out this great answer on the same question over at Stack Overflow.

In short, this is done for performance reasons, as processors typically fetch instructions in 16- or 32-byte strides, so it makes sense to have functions begin at one of these boundaries.

  • The last image shows function alignment on 0x00b4 instead. But that might just be compiled with a different optimization, or possibly a library function. – usr2564301 Apr 16 '14 at 21:50
  • @usr2564301 Note that the last image has the caption "old ELF binary"; it's what the OP was comparing against. – Jonathon Reinhart Feb 13 at 3:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.