title: Mac OS X 32-bit nasm assembly program using main and scanf/printf?
body: <p>I have spent the entire day trying to get some simple programs compiled but so far very little luck. What I want to do is to compile and run programs written in nasm assembly.</p>
  
  <p>I have upgraded to latest nasm (v2.10.09). So let me just jump into code since I do not know a lot about these things yet. Here is a chunk of assembly code that runs on linux using <code>elf</code> format and linked witch gcc (comments are my understanding of what is going on):</p>
  
  <pre><code>bits 32
  extern printf
  global main
  
  section .data
      message db "Hello world!", 10, 0
  
  section .text
  main:
      pushad                      ;push all registers on stack
      push dword message                  ;push the string on stack
      call printf                 ;call printf
      add esp, 4                  ;clear stack
      popad                       ;pop all registers back
      ret                     ;return to whoever called me
  </code></pre>
  
  <p>Nothing too big. However how the hell am I supposed to get this to work on OS X? I cant even get it to compile/link in any way. If it compiles I cant link it (something about i386 and x86 which cant be linked together (I understand that but how to fix it?)). I have tried a dozen ways with no luck.</p>
  
  <p>Further more how can I <code>printf</code> and <code>scanf</code> on OS X assembly?</p>
  
  <p>Here is another futile attempt of a <code>scanf</code> and <code>printf</code> the value back (this one actually compiles and links - and even runs!):</p>
  
  <pre><code>[bits 32] ; why the []?
  
  section .data
      input_string    db  "Enter limit: %d", 0
      output_string   db  "Value %d", 10, 0
      counter         dd  10
      limit           dd  0
  
  ;nasm -f macho -o test.o test.asm 
  ;ld -lc -o test -arch i386 test.o -macosx_version_min 10.7
  
  section .text
  
  global start
  extern _printf
  extern _scanf
  extern _exit
  
  start:
      push ebp                ;push stack base
      mov ebp, esp            ;base is now current top
      and esp, 0xFFFFFFF0     ;align the stack - WHY? I just googled this?
  
      sub esp, 16             ;16 bytes for variables - 16 to keep the stack "aligned". WHY?
  
      mov dword[esp], input_string         ;ordinary push just isint good nuff for mac... WHY?
      mov dword[esp + 4], limit
      call _scanf                          ;does scan something but doesnt print the message, it just scans and then prints the message
  
      mov eax, [limit]                      ;since i cant push this lets put it in eax first
  
  
      mov dword[esp + 8], output_string     ;push the output string. WHY again MOV?
      mov dword[esp + 12], eax              ;and the previusly "scanned" variable
      call _printf                          ;print it out
  
      mov dword[esp], 0       ;return value
      call _exit              ;return
  </code></pre>
  
  <p>Compiled it with: <code>nasm -f macho -o test.o test.asm</code> and linked it with <code>d -lc -o test -arch i386 test.o -macosx_version_min 10.7</code>. Doesnt work properly. On linux its super easy to to this scanf and printf thingie. What's up here? Can it be done simpler?</p>
  
  <p>I do not want to add more stuff to this question since people sometimes see a big question and thing "meh, too long, wont read". But if anyone requests more info I'll do my best.</p>
  
  <p>Please help me since I cant figure it out.</p>
  
  <p><strong>EDIT</strong>
  The first one compiles using <code>nasm -f macho -o out.o test.asm</code> but doest link using <code>gcc -o test out.o</code> or by using <code>ld -lc -o test -arch i386 out.o -macosx_version_min 10.7</code> and appending flat <code>-arch i386</code> doesnt solve it either. I would love if I could write that "linux like" assembly since I do not have to worry about stack alignment and stuff like that.
  gcc error says:</p>
  
  <pre><code>ld: warning: ignoring file out.o, file was built for i386 which is not the architecture being linked (x86_64): out.o
  Undefined symbols for architecture x86_64:
    "_main", referenced from:
        start in crt1.10.6.o
  ld: symbol(s) not found for architecture x86_64
  </code></pre>
  
  <p>and ld error is as follows:</p>
  
  <pre><code>Undefined symbols for architecture i386:
    "printf", referenced from:
        main in out.o
    "start", referenced from:
       -u command line option
  ld: symbol(s) not found for architecture i386
  </code></pre>
  
  <p>Please help.</p>