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\0"
billy_bones:
.ascii "Billy Bones\0"
black_beard:
.ascii "Black Beard\0"
dave_jones:
.ascii "Dave Jones\0"
jack_the_sparrow:
.ascii "Jack The Sparrow\0"
genry_morgan:
.ascii "Genry Morgan\0"
# 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. :(
CodePudding user response:
.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,