関数呼び出しの開始時にリンク レジスタをプッシュし、戻る前にその値をプログラム カウンターにポップする必要があることを理解しています。これにより、関数呼び出しの前の場所から実行が実行できるようになります。
私が理解していないのは、プッシュ/ポップに追加のレジスタを追加することで、ほとんどの人がこれを行う理由です。例えば:
push {ip, lr}
...
pop {ip, pc}
たとえば、ARM の公式ブログで提供されている ARM の Hello World は次のとおりです。
.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"
質問 1 : 「ダミー レジスタ」と呼ばれる理由は何ですか? 単純に {lr} を押して {pc} をポップしないのはなぜですか? スタックを 8 バイトに揃えるためだと言われていますが、スタックは 4 バイトに揃えられていませんか?
質問 2 : "ip" とはどのレジスターですか (つまり、r7 ですか?)