I’m getting errors when I try to use variables declared in the .data section and I’m not sure how to fix it.
My code (shortened):
section .data
you: db "you"
section .bss
output: resb 255
section .text
global two_fer
two_fer:
mov rdi, you
ret
%ifidn __OUTPUT_FORMAT__,elf64
section .note.GNU-stack noalloc noexec nowrite progbits
%endif
Error:
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: two_fer.o: warning: relocation in read-only section `.text'
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
make: *** [Makefile:32: tests] Error 1
I also get the below error with my full code. default rel
doesn’t fix it.
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: two_fer.o: relocation R_X86_64_32S against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:32: tests] Error 1
Look at the solution for Hello World.
It starts with
default rel
and the most important instruction used is lea
(load effective address).
I did not use section .bss
in my Two Fer solution. We are given an output pointer to write to.
I had already tried this a few minutes after posting this. No dice. Also, removing the .bss section seems to have no effect.
Here’s the full code:
default rel
section .data
oneFor: db "One for "
oneForLength: equ $ - oneFor
you: db "you"
youLength: equ $ - you
oneForMe: db ", one for me.", 0
oneForMeLength: equ $ - oneForMe
section .bss
output: resb 255
section .text
global two_fer
two_fer:
; Provide your implementation here
mov rbx, rdi
cld
; Put oneFor in the output
lea rsi, [oneFor]
lea rdi, [output]
mov rcx, oneForLength
rep movsb
mov rax, [rbx]
test rax, rax
jnz copy
; Put you in the output
lea rsi, [you]
lea rdi, [output + oneForLength]
mov rcx, youLength
rep movsb
mov rcx, youLength
jmp complete
; Put input in the output
copy:
mov al, byte [rbx+rcx]
test al, al
jz complete
mov byte [output + oneForLength + rcx], al
inc rcx
jmp copy
complete: ; Complete the output with oneForMe
lea rsi, [oneForMe]
lea rdi, [output + oneForLength + rcx]
mov rcx, oneForMeLength
rep movsb
lea rax, [output]
ret
%ifidn __OUTPUT_FORMAT__,elf64
section .note.GNU-stack noalloc noexec nowrite progbits
%endif
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: two_fer.o: relocation R_X86_64_32S against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:32: tests] Error 1
I coded this locally on my PC before moving it to Exercism editor.
I’m not aware of this. What output pointer were we given?
Exercism uses the System V Application Binary Interface, see Useful x86-64 Assembly resources.
From section 3.2.1
Registers %rbp
, %rbx
and %r12
through %r15
“belong” to the calling function and the called function is required to preserve their values. In other words, a called function must preserve these registers’ values for its caller.
It is common for functions that use rbx
to have push rbx
at the start of the function, and pop rbx
just before the return.
From section 3.2.3
Passing Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:
- If the class is MEMORY, pass the argument on the stack.
- If the class is INTEGER, the next available register of the sequence
%rdi
, %rsi
, %rdx
, %rcx
, %r8
and %r9
is used
If we look at the Two Fer tests, we have
extern void two_fer(const char *name, char *buffer);
So the read-only string name
is being passed in rdi
, and the buffer for the output string is being passed in rsi
.
Early in your code, you might have something like
mov r8, rdi ; name
mov rdi, rsi ; buffer