在链接目标文件时,我获得了对'esp'的未定义引用。
我在名为mydc.s的文件中编写了汇编代码
然后我使用
创建了目标文件 as --32 -march=i386 mydc.s -o mydc.o
(这里没有错误) 然后将其与
关联 gcc -m32 -march=i386 mydc.o -o mydc
然后它创建错误消息为
(。text + 0x2a):对'esp'的未定义引用
代码如下
.section ".text"
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
input:
pushl $buffer
pushl $scanfFormat
call scanf
addl $8, %esp
## check if user input EOF
cmp $EOF, %eax
je quit
pushl $buffer
call isdigit
addl $4, esp
cmp $1, %eax
je if_digit
movl buffer, %eax
cmpl $'p', %eax
je if_p
cmpl $'q', %eax
je if_q
cmpl $'+', %eax
je if_plus
if_p:
movl iIndex, %eax
sall $2, %eax
addl $stack, %eax
pushl %eax
pushl $resultFormat
call printf
addl $8, %esp
jmp input
我没有得到的是esp不是变量或函数,只是寄存器名,因此不应创建未定义的引用错误。
为什么会发生这种情况,我该如何解决?
答案 0 :(得分:5)
问题是由以下行引起的:
addl $4, esp
在其他任何地方,您都需要按照AT&T语法的要求,使用%
装饰器指定寄存器(例如,%esp
)。
此修饰符的全部目的是将寄存器名称与符号名称区分开-未经修饰的esp
是符号,而不是寄存器,就像if_digit
一样。
这说明了链接器为何试图查找称为esp
的内容(并失败)的原因。这也是为什么您的错误消息是Undefined reference to 'esp'
而不是'%esp'
的原因。
要求在寄存器名称上使用修饰符意味着,asm源代码可以防止将来引入新的寄存器名称。例如,如果您在购买SSE之前拥有一个名为xmm0
的全局变量,那么您的代码将不会与包含SSE支持的更高版本的汇编程序版本一起使用。