web-dev-qa-db-ja.com

ベースポインターとスタックポインター

このコードを考えると:

       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が最初のパラメータを指しているのですか?

34
yhcowboy

関数が呼び出されると、スタックは次のようになります。

+-------------+
| 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ファミリーでは間違いなく当てはまります)。そのため、スタックの一番上にあるメモリアドレスが最小になります。

49
Michael Burr

スタックには他に2つのアイテムがあるため、このルーチンの最初にプッシュする以前のebp、およびルーチンの呼び出しによってスタックに置かれる戻りアドレス。

7