.quad $label in AT&T syntax: undefined reference to [label-name]

.quad $label in AT&T syntax: undefined reference to [label-name]

Problem Description:

I learn assembler(AT&T). I tried to write program to find the length of the biggest string in record.
During linking with command

ld person-data-with-names-pointer.o find-longest-name.o -o longest

I got error

ld: person-data-with-names-pointer.o: in function `people':
(.data+0x55): undefined reference to `$john_silver'
ld: (.data+0x85): undefined reference to `$billy_bones'
ld: (.data+0xb5): undefined reference to `$black_beard'
ld: (.data+0xe5): undefined reference to `$dave_jones'
ld: (.data+0x115): undefined reference to `$jack_the_sparrow'
ld: (.data+0x145): undefined reference to `$genry_morgan'

full listing of person-data-with-names-pointer.s

.section .data

.global people, numpeople
numpeople:
    # Calculate the number of people in array
    .quad (endpeople - people)/PERSON_RECORD_SIZE
people:
    .quad $john_silver, 200, 10, 2, 74, 20 
    .quad $billy_bones, 280, 14, 2, 74, 44
    .quad $black_beard, 150, 8, 1, 68, 30
    .quad $dave_jones, 250, 14, 3, 75, 24
    .quad $jack_the_sparrow, 250, 10, 2, 70, 11
    .quad $genry_morgan, 180, 11, 5, 69, 65 
endpeople: # Marks the end of the array for calculation purposes

john_silver:
    .ascii "John Silver"
billy_bones: 
    .ascii "Billy Bones"
black_beard: 
    .ascii "Black Beard"
dave_jones: 
    .ascii "Dave Jones"
jack_the_sparrow: 
    .ascii "Jack The Sparrow"
genry_morgan:
    .ascii "Genry Morgan" 
# Describes the components of the struct
.global NAME_PTR_OFFSET, WEIGHT_OFFSET, SHOE_OFFSET 
.global HAIR_OFFSET, HEIGHT_OFFSET, AGE_OFFSET
.equ NAME_PTR_OFFSET, 0
.equ WEIGHT_OFFSET,  8
.equ SHOE_OFFSET, 16 
.equ HAIR_OFFSET, 24
.equ HEIGHT_OFFSET, 32
.equ AGE_OFFSET, 40
# Total size of the struct 
.global PERSON_RECORD_SIZE
.equ PERSON_RECORD_SIZE, 48

I was tried to move labels but nothing works. 🙁

Solution – 1

.quad isn’t a real instruction like mov; a symbol name will always be taken as the symbol address, and a $ will be taken as a literal part of the symbol name. As the linker error shows you, it’s looking for symbol names like $john_silver, not john_silver.

    .quad john_silver, 200, 10, 2, 74, 20 
    .quad billy_bones, 280, 14, 2, 74, 44

For the same reason you write .quad 123 not .quad $123.

Like most assemblers, there’s no syntax that will get GAS to copy data from one .quad or .string to another; if you wanted the same data in two places, you’d define a macro or .equ assemble-time constant and emit the same data separately. You can’t read back in some bytes emitted into an output section by a different source line.

So there’s nothing equivalent to the immediate vs. memory-operand possibility here, which is what $ distinguishes in instructions.

mov symbol, %rax is a load of 8 bytes from that address (using 32-bit absolute addressing, not RIP-relative), vs. mov $symbol, %rax is the address as a 32-bit sign-extended immediate.
In 64-bit code, normally you’d use mov symbol(%rip), %rax or lea symbol(%rip), %rax, or in non-PIE executables, 32-bit absolute mov $symbol, %eax. See How to load address of function or label into register

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject