未定义对“ esp”的引用

时间:2019-05-19 09:47:28

标签: assembly x86 gas att

在链接目标文件时,我获得了对'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不是变量或函数,只是寄存器名,因此不应创建未定义的引用错误。

为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:5)

问题是由以下行引起的:

addl    $4, esp

在其他任何地方,您都需要按照AT&T语法的要求,使用%装饰器指定寄存器(例如,%esp)。

此修饰符的全部目的是将寄存器名称与符号名称区分开-未经修饰的esp符号,而不是寄存器,就像if_digit一样。

这说明了链接器为何试图查找称为esp的内容(并失败)的原因。这也是为什么您的错误消息是Undefined reference to 'esp'而不是'%esp'的原因。


要求在寄存器名称上使用修饰符意味着,asm源代码可以防止将来引入新的寄存器名称。例如,如果您在购买SSE之前拥有一个名为xmm0的全局变量,那么您的代码将不会与包含SSE支持的更高版本的汇编程序版本一起使用。