无法在Assembly OS(x86-64)和Mac OSX上的C文件中链接printf和scanf

Sir*_*blk 3 c macos assembly printf nasm

我在Assembly(x86-64)中编写了一个程序,并从C文件包装器调用它来使用printf和scanf函数.但是,当我尝试链接它时,我收到以下错误:

$ 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
Run Code Online (Sandbox Code Playgroud)

我相信这与macho64旗帜有关.如果我使用elf64,它将不会捕获printf或scanf错误.但是,elf64在Mac上是一种不兼容的文件格式(据我所知).

这是我的C文件(ParallelogramDriver.c):

#include <stdio.h>
#include <stdint.h> //For C99 compatability

extern int calcAndPrint();

int main(int argc, char* argv[])
{
    //Run Assembly Code
    calcAndPrint();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

最后这是我的汇编代码(Parallelograms.asm):

;==== 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 ====
Run Code Online (Sandbox Code Playgroud)

为凌乱的代码道歉.这是我的第一个汇编代码程序,我对它很新.我正在开发Mac OSX,据我所知这是Mac OSX特有的问题.谢谢你的帮助.

小智 5

在OS X上,符号以下划线为前缀.

call        printf
Run Code Online (Sandbox Code Playgroud)

call        scanf
Run Code Online (Sandbox Code Playgroud)

需要

call        _printf
Run Code Online (Sandbox Code Playgroud)

call        _scanf
Run Code Online (Sandbox Code Playgroud)

分别; 也

global calcAndPrint
Run Code Online (Sandbox Code Playgroud)

calcAndPrint:
Run Code Online (Sandbox Code Playgroud)

应该读

global _calcAndPrint
Run Code Online (Sandbox Code Playgroud)

_calcAndPrint:
Run Code Online (Sandbox Code Playgroud)

代替.

(但是,嘿,你可以从你的calcAndPrint()功能被象征化的事实推断出这一点_calcAndPrint).

  • 将`--prefix _`添加到Nasm的命令行应该(?)修复此问题(作为在.asm源中添加下划线的替代方法). (2认同)