2

On OSX 64bit, compiling a dummy C program like that:

#include <stdio.h>

void foo1() {
}

void foo2() {
}

int main() {
        printf("Helloooo!\n");
        foo1();
        foo2();
        return 0;
}

Produces the following ASM code (obtained disassembling the binary with otool):

(__TEXT,__text) section
_foo1:
0000000100000f10    55                  pushq   %rbp
0000000100000f11    4889e5              movq    %rsp, %rbp
0000000100000f14    897dfc              movl    %edi, -0x4(%rbp)
0000000100000f17    5d                  popq    %rbp
0000000100000f18    c3                  retq
0000000100000f19    0f1f8000000000      nopl    (%rax)
_foo2:
0000000100000f20    55                  pushq   %rbp
0000000100000f21    4889e5              movq    %rsp, %rbp
0000000100000f24    5d                  popq    %rbp
0000000100000f25    c3                  retq
0000000100000f26    662e0f1f840000000000    nopw    %cs:(%rax,%rax)
_main:
0000000100000f30    55                  pushq   %rbp
0000000100000f31    4889e5              movq    %rsp, %rbp
0000000100000f34    4883ec10            subq    $0x10, %rsp
0000000100000f38    488d3d4b000000      leaq    0x4b(%rip), %rdi        ## literal pool for: "Helloooo!\n"
0000000100000f3f    c745fc00000000      movl    $0x0, -0x4(%rbp)
0000000100000f46    b000                movb    $0x0, %al
0000000100000f48    e81b000000          callq   0x100000f68             ## symbol stub for: _printf
0000000100000f4d    bf06000000          movl    $0x6, %edi
0000000100000f52    8945f8              movl    %eax, -0x8(%rbp)
0000000100000f55    e8b6ffffff          callq   _foo1
0000000100000f5a    e8c1ffffff          callq   _foo2
0000000100000f5f    31c0                xorl    %eax, %eax
0000000100000f61    4883c410            addq    $0x10, %rsp
0000000100000f65    5d                  popq    %rbp
0000000100000f66    c3                  retq

What are the "nop" instructions found right after the "ret" on functions foo1() and foo2()? They are, of course, never executed since the "ret" instructions return from the function call. Is that any kind of padding or it has a different meaning?

phuclv
  • 37,963
  • 15
  • 156
  • 475
ASLLOP
  • 174
  • 2
  • 12
  • 4
    They're used for alignment purposes - i.e their inclusion means that _foo2 and _main are aligned to 16 byte boundaries, which leads to faster execution. – enhzflep Nov 25 '15 at 18:02
  • 2
    If you look at the program counter on the left, the functions are 16-byte aligned. – Weather Vane Nov 25 '15 at 18:03
  • Great! It makes sense. Thnx for your quick answer guys! – ASLLOP Nov 25 '15 at 18:10
  • @enhzflep there is any special reason to use a strangely codified "nop" operation instead of simply zeros? – ASLLOP Nov 25 '15 at 18:14
  • @MichaelPetch OS X uses clang. But they are *similar* questions. – Elliott Frisch Nov 25 '15 at 22:43
  • 2
    @ElliottFrisch IMHO It is effectively a duplicate. The platforms may be different but the ultimate question is pretty much the same, and the answers there IMHO are better than the ones here. Unless one can find reasons why icc/clang/gcc for Intel based platforms targeting Windows/Linux/OSX(BSD) etc pad functions is somehow done for much different reasons, I'll consider this a duplicate. – Michael Petch Nov 25 '15 at 22:46

3 Answers3

5

From the Assembly language for x86 processors, Kip R. Irvine

The safest (and the most useless) instruction you can write is called NOP (no operation). It takes up 1 byte of program storage and doesn’t do any work. It is sometimes used by compilers and assemblers to align code to even-address boundaries

00000000 66 8B C3 mov ax,bx  
00000003 90 nop ; align next instruction  
00000004 8B D1 mov edx,ecx  
Enkelli
  • 305
  • 5
  • 18
2

What are the "nop" instructions found right after the "ret" on functions foo1() and foo2()?

The nop is a no-operation instruction (do nothing), from the linked Wikipedia page (emphasis mine)

A NOP is most commonly used for timing purposes, to force memory alignment, to prevent hazards, to occupy a branch delay slot, to render void an existing instruction such as a jump, or as a place-holder to be replaced by active instructions later on in program development (or to replace removed instructions when refactoring would be problematic or time-consuming).

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0

nop is short for No Operation. The nop instructions in this case are providing execution code alignment. Notice that labels are on 16 byte boundaries. On OSX, the linker (ld) should have a -segalign option that will affect this behavior.

Duane McCully
  • 406
  • 3
  • 6