3

アセンブリ(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 ====

厄介なコードについてお詫びします。これは私の最初のアセンブリコードプログラムであり、非常に新しいものです。私はMacOSXで開発していますが、私の知る限り、これはMacOSX固有の問題です。ご協力いただきありがとうございます。

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 に答える