I am trying to use a macro (as shown in this tutorial) to print a string. The macro PRINT creates local labels to define the string content (str) and length (strlen), and then passes these as parameters to a second macro _syscall_write which makes the syscall.
However running the code fails and I get a Segmentation fault (core dumped) message.
I suspect the problem to be this particular lines, but I don't understand why.
mov rsi, %1 ; str
mov rdx, %2 ; strln
Here is the full code:
%macro PRINT 1
; Save state
push rax
push rdi
push rsi
push rdx
%%str db %1, 0 ; arg0 + null terminator
%%strln equ $ - %%str ; current position - string start
; Write
_syscall_write %%str, %%strln
; Restore state
pop rdx
pop rsi
pop rdi
pop rax
%endmacro
%macro _syscall_write 2
mov rax, 1
mov rdi, 1
mov rsi, %1 ; str
mov rdx, %2 ; strln
syscall
%endmacro
global _start
section .data
SYS_EXIT equ 60
EXIT_CODE equ 0
section .text
_start:
PRINT "Hello World!"
exit:
mov rax, SYS_EXIT
mov rdi, EXIT_CODE
syscall
Here is a disassembly of the object file (from a version with the push/pop commented out).
Looking at the expanded code I still cannot see what is wrong. The bytes 0x0..0xC look like gibberish but correspond to the ascii code of the characters in Hello World!. Before the syscall to sys_write, rax and rdi seem to receive the expected value of 0x1, rsi the value of 0x0 which points to the string start, and rdx the value of 0xd which is the string length (12 + 1)...
Disassembly of section .text:
0000000000000000 <_start>:
0: 48 rex.W
1: 65 gs
2: 6c ins BYTE PTR es:[rdi],dx
3: 6c ins BYTE PTR es:[rdi],dx
4: 6f outs dx,DWORD PTR ds:[rsi]
5: 20 57 6f and BYTE PTR [rdi+0x6f],dl
8: 72 6c jb 76 <SYS_EXIT+0x3a>
a: 64 21 00 and DWORD PTR fs:[rax],eax
d: b8 01 00 00 00 mov eax,0x1
12: bf 01 00 00 00 mov edi,0x1
17: 48 be 00 00 00 00 00 movabs rsi,0x0
1e: 00 00 00
21: ba 0d 00 00 00 mov edx,0xd
26: 0f 05 syscall
0000000000000028 <exit>:
28: b8 3c 00 00 00 mov eax,0x3c
2d: bf 00 00 00 00 mov edi,0x0
32: 0f 05 syscall