Tutorial :I'm learning x86 assembly on OS X 10.6, how do I compile?


I'm about to learn x86 assembly language on Mac OS X. I'm using as instruction to compile assembly file in commend window. But I have several errors and I don't know how I can get through.

Here are the errors and my assembly code, which is quite simple.

**ung-mi-lims-macbook-pro:pa2 ungmi$ as swap.s  swap.s:16:Unknown pseudo-op: .type  swap.s:16:Rest of line ignored. 1st junk character valued 115 (s).  swap.s:19:suffix or operands invalid for `push'  swap.s:46:suffix or operands invalid for `pop'  ung-mi-lims-macbook-pro:pa2 ungmi$**   

and the source is

.text          .align 4  .globl  swap          .type swap,@function    swap:          pushl   %ebp          movl    %esp, %ebp            movl    %ebp, %esp          popl    %ebp          ret  

and I searched some solution which is I have to put -arch i386 than

**ung-mi-lims-macbook-pro:pa2 ungmi$ as -arch i386 swap.s  swap.s:16:Unknown pseudo-op: .type  swap.s:16:Rest of line ignored. 1st junk character valued 115 (s).  ung-mi-lims-macbook-pro:pa2 ungmi$**   

Could you help me out? Just let me know what I need to compile assembly file. I have XCode already and I'd rather to do this with commend window and vi editor.


Your code is 32-bit assembly. Compilation on Snow Leopard is 64-bit by default, but you can use gcc -m32 for compiling 32-bit code. There are of course also options that you can pass to as and ld but I found that remembering only the option for gcc was enough, since it is a front-end to all these things.

Use gcc to show you an example of assembly code that works: type a minimal C function in file test.c and use gcc -S test.c to produce the assembly in file test.s.


int x;    void f(void)  {    int i;    for (i = 0; i < 5; i++)  x = x + 1;  }  

is compiled in assembly on this Leopard Mac:

    .text  .globl _f  _f:      pushl   %ebp      movl    %esp, %ebp      subl    $24, %esp      call    L6  "L00000000001$pb":  L6:      popl    %ecx      movl    $0, -12(%ebp)      jmp L2  L3:      leal    L_x$non_lazy_ptr-"L00000000001$pb"(%ecx), %eax      movl    (%eax), %eax      movl    (%eax), %eax      leal    1(%eax), %edx      leal    L_x$non_lazy_ptr-"L00000000001$pb"(%ecx), %eax      movl    (%eax), %eax      movl    %edx, (%eax)      leal    -12(%ebp), %eax      incl    (%eax)  L2:      cmpl    $4, -12(%ebp)      jle L3      leave      ret  .comm _x,4,2      .section __IMPORT,__pointers,non_lazy_symbol_pointers  L_x$non_lazy_ptr:      .indirect_symbol _x      .long   0      .subsections_via_symbols  

You can make it simpler by using gcc option -fno-PIC:

    .text  .globl _f  _f:      pushl   %ebp      movl    %esp, %ebp      subl    $24, %esp      movl    $0, -12(%ebp)      jmp L2  L3:      movl    _x, %eax      incl    %eax      movl    %eax, _x      leal    -12(%ebp), %eax      incl    (%eax)  L2:      cmpl    $4, -12(%ebp)      jle L3      leave      ret  .comm _x,4,2      .subsections_via_symbols  

On Snow Leopard you will get 64-bit assembly (amd64). You could get the same thing on Leopard by using the -m64 gcc option, and you can get on Snow Leopard the same thing you'd get running gcc on Leopard with the -m32 option.


Use GCC, it'll compile and link for you: cc swap.s


Apple's as is forked from binutils 1.38, while the current version is 2.20, so there may be many new directives not available. I can't find the manual for 1.38, but the oldest one (2.10) I could find states that .type is associated only with COFF format output. The object format on Mac is Mach-O, so the .type directive is meaningless. Just remove it.


Recently I have ran in to this issue as well trying to compile Intel x86 on Mac OS X:

For nasm:

-o hello.tmp - outfile  -f macho - specify format  Linux - elf or elf64  Mac OSX - macho  

For ld:

-arch i386 - specify architecture (32 bit assembly)  -macosx_version_min 10.6 (Mac OSX - complains about default specification)  -no_pie (Mac OSX - removes ld warning)  -e main - specify main symbol name (Mac OSX - default is start)  -o hello.o - outfile  

For Shell:

./hello.o - execution  


nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o  

Let me know if this helps!

I wrote how to do it on my blog here:


For a more verbose explanation, I explained on my Github here:


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »