Durch einige Manipulation habe ich es auf ein Problem mit der ret
OP eingegrenzt. Ich weiß call
schiebt die Rücksprungadresse zum Stapel; Ist es illegal, es zu knacken und zurückzuschieben?Warum bekomme ich einen segfault, wenn ich "ret"? (FASM)
format ELF64 executable 3
entry start
segment readable executable
start:
pop rcx ; argc
mov [argc],cl ; int -> ASCII
add [argc],'0'
push 1 argc 1
call sys_write
mov rdi,0
mov rax,60
syscall
sys_write: ; (fd,*buf,count)
pop r11
pop rdx rsi rdi
mov rax,1
syscall
push r11
ret
segment readable writable
argc rb 1
Ausgang ist:
$ ./prog
1Segmentation fault
$ _
SYSCALL zerstört r11. Sie hätten fast jedes andere Register auswählen können. Aber es ist viel einfacher, Funktionsargumente in Registern zu übergeben (wie es die ABI-Standard-Aufrufkonvention tut) oder den Stapel mit 'mov ..., [rsp + 8]' zu lesen. Die 'pop rdx rsi rdi'-Syntax von FASM ist nur syntaktischer Zucker, und sie besteht immer noch aus 3 Anweisungen. Dies ist nicht effizient. –
Wenn Sie einen Debugger verwendet hätten, hätten Sie die Registerwerte überprüfen können. –
Sie müssen mich verarschen. Nun, 'r12' hat funktioniert. Nur mein Glück. Vielen Dank. – qrpnxz