このコードを考えると:
swap:
Push ebp ; back up the base pointer,
mov ebp, esp
; Push the context of the registers on the stack
Push eax
Push ebx
Push ecx
Push edx
mov eax, [ebp+8] ; address of the first parameter
mov ebx, [ebp+12] ; address of the second parameter
mov dl, [eax]
mov cl, [ebx]
mov [eax], cl
mov [ebx], dl
; restore the context of the registers from the stack
pop edx
pop ecx
pop ebx
pop eax
; restore the ebp
pop ebp
ret
(これは単なるメソッドです。以前は、1番目と2番目のパラメーターをスタックにプッシュしていました。)
私の質問は、最初のパラメーターのアドレスを取得するためにベースポインターに8を追加し、次に12を追加するのはなぜですか?
私はそれらがdwordであるという事実を得て、それらのそれぞれが4バイトになります。したがって、ebp + 8からebp + 12までは、意味のあるものになります。しかし、なぜ最初のものがebp + 8なのか?なぜならESPがスタックのTOPを指している場合、mov ebp、espは、EBPがスタックのTOPを指していることを意味します。次に、スタックに4つの値をプッシュします:eax、ebx、ecxおよびedx。なぜEBP + 8が最初のパラメータを指しているのですか?
関数が呼び出されると、スタックは次のようになります。
+-------------+
| Parameter 2 |
+-------------+
| Parameter 1 |
+-------------+
| Return Addr | <-- esp
+-------------+
「スタックフレーム」が設定された後:
+-------------+
| Parameter 2 | <-- [ebp + 12]
+-------------+
| Parameter 1 | <-- [ebp + 8]
+-------------+
| Return Addr |
+-------------+
| saved ebp | <-- ebp
+-------------+ <-- esp
これでコンテキストが保存されました:
+-------------+
| Parameter 2 | <-- [ebp + 12]
+-------------+
| Parameter 1 | <-- [ebp + 8]
+-------------+
| Return Addr |
+-------------+
| saved ebp | <-- ebp
+-------------+
| saved eax |
+-------------+
| saved ebx |
+-------------+
| saved ecx |
+-------------+
| saved edx | <-- esp
+-------------+
多くのシステムではスタックが下向きに成長することを忘れないでください(これはx86ファミリーでは間違いなく当てはまります)。そのため、スタックの一番上にあるメモリアドレスが最小になります。
スタックには他に2つのアイテムがあるため、このルーチンの最初にプッシュする以前のebp、およびルーチンの呼び出しによってスタックに置かれる戻りアドレス。