3

我在 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

我相信这与 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;
}

最后是我的汇编代码(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 ====

为混乱的代码道歉。这是我的第一个汇编代码程序,我对它很陌生。我正在 Mac OSX 上开发,据我所知,这是 Mac OSX 特定的问题。谢谢你的帮助。

4

1 回答 1

5

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

call        printf

call        scanf

需要

call        _printf

call        _scanf

分别; 还

global calcAndPrint

calcAndPrint:

应该读

global _calcAndPrint

_calcAndPrint:

反而。

calcAndPrint()(但是,嘿,您可以从您的函数被符号化为的事实推断出这一点_calcAndPrint)。

于 2013-02-04T21:55:00.253 回答