Capisco che ho bisogno di spingere il registro di collegamento all'inizio di una chiamata di funzione, e inserire quel valore nel Program Couter prima di tornare, in modo che l'esecuzione possa portarne uno da dove era prima della chiamata di funzione.ARM: Perché devo premere/inserire due registri nelle chiamate di funzione?
Quello che non capisco è perché la maggior parte delle persone lo fa aggiungendo un registro extra al push/pop. Per esempio:
push {ip, lr}
...
pop {ip, pc}
Per esempio, ecco un mondo Ciao a ARM, forniti dal official ARM blog:
.syntax unified
@ --------------------------------
.global main
main:
@ Stack the return address (lr) in addition to a dummy register (ip) to
@ keep the stack 8-byte aligned.
push {ip, lr}
@ Load the argument and perform the call. This is like 'printf("...")' in C.
ldr r0, =message
bl printf
@ Exit from 'main'. This is like 'return 0' in C.
mov r0, #0 @ Return 0.
@ Pop the dummy ip to reverse our alignment fix, and pop the original lr
@ value directly into pc — the Program Counter — to return.
pop {ip, pc}
@ --------------------------------
@ Data for the printf calls. The GNU assembler's ".asciz" directive
@ automatically adds a NULL character termination.
message:
.asciz "Hello, world.\n"
Domanda 1: qual è la ragione per "registro fittizio" il come lo chiamano ? Perché non spingere semplicemente {lr} e pop {pc}? Dicono che è per mantenere allineato lo stack di 8 byte, ma non è allineato lo stack di 4 byte?
Domanda 2: ciò che registro è "ip" (vale a dire, R7 o cosa?)
Ho collegato a un post del blog ARM in cui raccomandano questo modello a due registri. Si prega di controllare, c'è del codice lì. –
utilizzando i collegamenti è sconsigliato su SO, perché il collegamento potrebbe non durare fino a quando la domanda (e/o semplicemente rimuovere la domanda perché utilizza collegamenti piuttosto che avere la discussione qui). –
ahh, quindi il link risponde alla tua domanda. Puoi pubblicare la risposta da solo. e chiudi questa domanda. –