title: Trouble linking printf and scanf in Assembly (x86-64) and C file on Mac OSX
body: <p>I wrote a program in Assembly (x86-64) and called it from a C file wrapper to use both the printf and scanf functions. However when I try to link it I get the following errors:</p>
  
  <pre><code>$ nasm -f macho64 -l Parallelograms.lis -o assembly.o Parallelograms.asm
  $ gcc -c -Wall -m64 -o main.o ParallelogramDriver.c
  $ gcc -m64 -o main.out main.o assembly.o
  Undefined symbols for architecture x86_64:
    "_calcAndPrint", referenced from:
        _main in main.o
    "printf", referenced from:
        calcAndPrint in assembly.o
    "scanf", referenced from:
        calcAndPrint in assembly.o
  ld: symbol(s) not found for architecture x86_64
  collect2: ld returned 1 exit status
  </code></pre>
  
  <p>I believe it's related to the macho64 flag. If I were to use elf64 it wouldn't catch the printf or scanf error. However elf64 is an incompatible file format on Macs (as I understand it).</p>
  
  <p>Here's my C file (ParallelogramDriver.c):</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdint.h&gt; //For C99 compatability
  
  extern int calcAndPrint();
  
  int main(int argc, char* argv[])
  {
      //Run Assembly Code
      calcAndPrint();
  
      return 0;
  }
  </code></pre>
  
  <p>And finally here's my Assembly code (Parallelograms.asm):</p>
  
  <pre><code>;==== Begin code area ====
  extern printf                                       ;External C function for output
  extern scanf                                        ;External C function for input
  extern sin                                          ;External C function for sin math function
  
  segment .data                                       ;Place initialized data in this segment
  
      stringData db "%s", 10, 0
      input1 db "Enter the length of one side of the parallelogram: ", 0
      input2 db "Enter the length of the second side of the parallelogram: ", 0
      input3 db "Enter the size in degrees of the included angle: ", 0
  
      floatOutput db "You entered: %5.2Lf", 0         ;Don't forget the uppercase L
  
      floatData db "%Lf", 0
  
  segment .bss                                        ;Place uninitialized data in this segment
  
      ;Currently this section is empty
  
  segment .text                                       ;Place executable statements in this segment
  
      global calcAndPrint
  
  calcAndPrint:                                       ;Entry Point Label.
  
  ;==== Necessary Operations! Do not remove!
      push        rbp                                 ;Save a copy of the stack base pointer !IMPORTANT
      push        rdi                                 ;Save since we will use this for our external printf function
      push        rsi                                 ;Save since we will use this for our external printf function
  
  ;==== Enable Floating Point Operations
      finit                                           ;Reset pointers to st registers; reset control word, status word, and tag word.
  
  ;============ INPUT 1 ==============
  ;==== Ask for first input
      mov qword   rax, 0                              ;A zero in rax indicates that printf receives standard parameters
      mov         rdi, stringData
      mov         rsi, input1
      call        printf
  
  ;==== Grab input from Keyboard
      mov qword  rax, 0                               ;A zero in rax indicates that printf receives standard parameters
      mov        rdi, floatData                       ;Tell scanf to accept a long float as the data input
      push qword 0                                    ;8 byes reserved. Need 10 bytes
      push qword 0                                    ;Another 8 bytes reserved for a total of 16 bytes
      mov        rsi, rsp                             ;rsi now points to the 16 bytes we have open. (rsp = Stack Pointer)
      call       scanf                                ;C now uses the scanf function
  
  ;==== Copy 10 byte number into Float space
      fld tword  [rsp]                                ;Load Float space and push rsp into the float stack. (braquests de-reference)
  
  ;============ INPUT 2 ==============
  ;=== Ask for second input
      mov qword   rax, 0                              ;A zero in rax indicates that printf receives standard parameters
      mov         rdi, stringData
      mov         rsi, input2
      call        printf
  
  ;==== Grab input from Keyboard
      mov qword  rax, 0                               ;A zero in rax indicates that printf receives standard parameters
      mov        rdi, floatData                       ;Tell scanf to accept a long float as the data input
      push qword 0                                    ;8 byes reserved. Need 10 bytes
      push qword 0                                    ;Another 8 bytes reserved for a total of 16 bytes
      mov        rsi, rsp                             ;rsi now points to the 16 bytes we have open. (rsp = Stack Pointer)
      call       scanf                                ;C now uses the scanf function
  
  ;==== Copy 10 byte number into Float space
      fld tword  [rsp]                                ;Load Float space and push rsp into the float stack. (braquests de-reference)
  
  ;============ INPUT 3 ==============
  ;=== Ask for third input
      mov qword   rax, 0                              ;A zero in rax indicates that printf receives standard parameters
      mov         rdi, stringData
      mov         rsi, input3
      call        printf
  
  ;==== Grab input from Keyboard
      mov qword   rax, 0                              ;A zero in rax indicates that printf receives standard parameters
      mov         rdi, floatData                      ;Tell scanf to accept a long float as the data input
      push qword  0                                   ;8 byes reserved. Need 10 bytes
      push qword  0                                   ;Another 8 bytes reserved for a total of 16 bytes
      mov         rsi, rsp                            ;rsi now points to the 16 bytes we have open. (rsp = Stack Pointer)
      call        scanf                               ;C now uses the scanf function
  
  ;==== Copy 10 byte number into Float space
      fld tword  [rsp]                                ;Load Float space and push rsp into the float stack. (braquests de-reference)
  
  ;============ TEMP ==============
  
  ;============ Output ==============
      mov qword   rax, 0
      mov         rdi, floatOutput
      mov qword   rax, 1                              ;Important for floats??!
      push qword  0                                   ;8 bytes reserved
      push qword  0                                   ;16 bytes reserved
      fstp tword [rsp]                                ;Pop the fp number from the FP stack into the storage at [rsp]
      call       printf
  
  ;============ Restore Registers ============
      pop rsi
      pop rdi
      pop rbp                                         ;Restore base pointer
  
  ;==== Time to exit this function ====
  ;Prepare to exit from this function
      mov qword rax, 0                                ;A zero in rax is the code indicating a successful execution.
      ret                                             ;ret pops the stack taking away 8 bytes
  
  ;==== End of function calcAndPrint ====
  </code></pre>
  
  <p>Apologies for the messy code. This is my first Assembly code program and I'm very new to it. I'm developing on Mac OSX and to my knowledge this is a Mac OSX specific issue. Thanks for your help.</p>