Search code examples
assemblyx86gnu-assembleratt

Undefined reference to 'esp'


I got undefined reference to 'esp', while linking my object file.

I wrote my assembly code in file named mydc.s

Then I created object file using

as --32 -march=i386 mydc.s -o mydc.o

(There was no error here) Then linked it with

gcc -m32 -march=i386 mydc.o -o mydc

Then it created error message as

(.text+0x2a): undefined reference to 'esp'

The code is as following

    .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

What I don't get is that esp is not a variable or function, just a register name, and thus should not create no undefined reference error.

Why does this happen, and how can I fix this?


Solution

  • The problem is caused by this line:

    addl    $4, esp
    

    Everywhere else, you specify registers with the % decorator, as required by AT&T syntax (%esp, for example).

    The whole point of this decorator is to distinguish register names from symbol names - the undecorated esp is a symbol rather then a register, just like if_digit.

    This explains why the linker is trying to find something called esp (and failing). It's also why your error message is Undefined reference to 'esp', as opposed to '%esp'.


    Requiring decorators on register names means that asm source is future-proof against introduction of new register names. For example if you had a global variable called xmm0 before SSE was bought into existence, your code wouldn't break with a later assembler version that included SSE support.