Reputation: 15
I'm currently working on assembly code. I wrote a program which genererate the following code. The generated code is exactly what I expect, but when I read it, the normal behaviour to me is that the assembly code will write to stdout an infinite number of '1' (in an infinite loop). The problem is that it writes only one '1' character and close without seg fault.
So, what I really missed from this code ? I wrote some comments to help me understand it, but after read and read again I don't see where is the problem. Is there a side effect in my code that I don't understand ?
Thanks.
.text
.globl main
main:
push %rbx
push %rbp
mov %rsp,%rbp
mov $208,%r10
push %rdi
mov %r10,%rdi
call test
pop %rdi
mov %rbp,%rsp
pop %rbp
mov %r9,%rax
pop %rbx
ret
test:
push %rbp
mov %rsp,%rbp
mov $9,%rax # Reserve memory slot for var i
push %rax #
mov $9,%rax # Reserve memory slot for var p
push %rax #
mov $196,%r10 # 196 -> r10
mov %r10,8(%rsp) # r10 -> i
jmp loop
loop:
mov $512,%r10 # 512 -> r10
mov 8(%rsp),%r11 # i -> r11
cmp %r10,%r11 # CMP 512 i
mov %r11,8(%rsp) # r11 -> i
jl less
jmp end
less:
#mov $40,%r10 # 40 -> r10
push %rdi # Save rdi (fs+1)
mov 16(%rsp),%r11 # i -> r11
mov %r11,%rdi # r11 -> rdi
call putchar # call putchar
pop %rdi # Restore rdi (fs-1)
#mov %r10,(%rsp) # r10 -> p
mov %r11,8(%rsp) # r11 -> i
jmp loop
end:
mov %rbp,%rsp
pop %rbp
ret
putchar:
mov %rdi,%rax
sar $2,%rax
push %rax
mov %rsp,%rsi
mov $1,%rdx
mov $1,%rdi
mov $1,%rax
syscall
pop %rax
mov $9,%rax
ret
EDIT
Solution : write syscall modify r11 register
Upvotes: 0
Views: 256
Reputation: 58762
The System V Application Binary Interface AMD64 Architecture Processor Supplement section A.2 AMD64 Linux Kernel Conventions says, among other things, that:
A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.
Upvotes: 1