hello: push rbp ; robimy ramkę stosu mov rbp, rsp sub rsp, 16 ; stack musi być wyrównany do 16 bajtów w SysV ABI, ofc w tym przykładzie w ogóle nie muszę sobie robić tych 16 bajtów, bo ich nie używam, ale wstawiam, żeby napisać ten komentarz o wyrównaniu stosu :P mov rcx, 10 ; loop counter hello_loop: mov rdi, hello_fmt mov rsi, rcx push rcx ; zapisuję rcx, bo _printf bruździ w rejestrach push rcx ; a ponieważ stos musi być wyrównany do 16 B to musimy albo zrobić sub rsp, 8 albo dwa razy zrobić push, inaczej dostaniemy segfaulta call _printf pop rcx ; przywracam rcx pop rcx ; wyrównuję stos loop hello_loop add rsp, 16 ; zwalniamy stos pop rbp ret section .data hello_fmt: db "Hello, %d", 10, 0 No i wszystko ładnie. Tylko dlaczego to wyrównanie nie tyczy się to pierwszego push rbp? Na początku mamy odjęte 8 (push rbp), potem 16 (sub rsp, 16), potem drugie 16 (podwójny push). To gdzie jest brakujące 8?
Na początku mamy odjęte 8 (push rbp), potem 16 (sub rsp, 16), potem drugie 16 (podwójny push). To gdzie jest brakujące 8?
@zwei: Te 8 bajtów zostanie zajęte przez "return adress" pod który ma wrócic funkcja po wywołaniu. Jest to zazwyczaj odkładane na stosie przez "call" i zdejmowane przez "ret"
Mam coś takiego
hello:push rbp ; robimy ramkę stosu
mov rbp, rsp
sub rsp, 16 ; stack musi być wyrównany do 16 bajtów w SysV ABI, ofc w tym przykładzie w ogóle nie muszę sobie robić tych 16 bajtów, bo ich nie używam, ale wstawiam, żeby napisać ten komentarz o wyrównaniu stosu :P
mov rcx, 10 ; loop counterhello_loop:mov rdi, hello_fmt
mov rsi, rcx
push rcx ; zapisuję rcx, bo _printf bruździ w rejestrach
push rcx ; a ponieważ stos musi być wyrównany do 16 B to musimy albo zrobić sub rsp, 8 albo dwa razy zrobić push, inaczej dostaniemy segfaulta
call _printf
pop rcx ; przywracam rcx
pop rcx ; wyrównuję stos
loop hello_loop
add rsp, 16 ; zwalniamy stospop rbp
ret
section .datahello_fmt: db "Hello, %d", 10, 0
No i wszystko ładnie. Tylko dlaczego to wyrównanie nie tyczy się to pierwszego
push rbp? Na początku mamy odjęte 8 (push rbp), potem 16 (sub rsp, 16), potem drugie 16 (podwójnypush). To gdzie jest brakujące 8?No ale powiem jak jest u mnie
Na początku to na studiach miałem 16-bitowy asm w MSDOS i potem jeszcze MIPS, takie zupełne podstawy. Jeden projekt z zamianą tekstu, drugi jakiś
https://www.youtube.com/watch?v=OTLyD2EEN0w&list=PL7CA8FE35B665D4DD
@zwei: Te 8 bajtów zostanie zajęte przez "return adress" pod który ma wrócic funkcja po wywołaniu. Jest to zazwyczaj odkładane na stosie przez "call" i zdejmowane przez "ret"