While i was trying do use brk (int 0x80 with 45 in %rax) to implement a simple memory manager program in assembly and print the blocks in order, i kept getting segfault. After a while i could only reproduce the error, but have no idea why is this happening:
.section .data
helloworld:
.ascii "hello world"
.section .text
.globl _start
_start:
push %rbp
mov %rsp, %rbp
movq $45, %rax
movq $0, %rbx #brk(0) should just return the current break of the programm
int $0x80
#incq %rax #segfault
#addq $1, %rax #segfault
movq $0, %rax #works fine?
#addq $1, %rax #segfault again?
movq $helloworld, %rdi
call printf
movq $1, %rax #exit
int $0x80
In the example here, if the commented lines are uncommented, i have a segfault, but some commands (like de movq $0, %rax) work just fine. In my other program, the first couple printf work, but the third crashes... Looking for other questions, i heard that printf sometimes allocates some memory, and that the brk shouldn't be used, because in this case it corrupts the heap or something... I'm very confused, does anyone know something about that?
EDIT: I've just found out that for printf to work you need %rax=0.
Your next problem is that the x86_64 system call calling convention uses %rdi, %rsi, %rdx, %r10, %r8 and %r9 to pass up to six arguments in that order (rather than the %ebx, %ecx, %edx, %esi, %edi, %ebp used in x86_32).
Therefore, you have to put brk
's first argument in %rdi:
movq $12, %rax
movq $0, %rdi
syscall
On kernels that support it, using int 0x80
will actually invoke 32-bit system calls with 32-bit call numbers and register assignments (for compatibility). If you had a kernel like that then your code snippet should have worked. If you did not, then your program would die as soon as it executed int 0x80
.