我在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的问题。谢谢你的帮助。
答案 0 :(得分:5)
在OS X上,符号以下划线为前缀。
call printf
和
call scanf
需要
call _printf
和
call _scanf
分别还
global calcAndPrint
和
calcAndPrint:
应该阅读
global _calcAndPrint
和
_calcAndPrint:
代替。
(但是,嘿,你可以从calcAndPrint()
函数被象征为_calcAndPrint
)的事实推断出这一点。