Подтвердить что ты не робот

Базовый указатель и указатель стека

Учитывая этот фрагмент кода:

       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

(Это только метод. Раньше мы вставляли первый и второй параметры в стек.)

Мой вопрос: почему мы добавляем 8 к базовому указателю, чтобы получить адрес первого параметра, а затем 12?

Я получаю тот факт, что они являются dword, поэтому каждый из них имеет 4 байта. С ebp + 8 до ebp + 12 это делает смысл делать. Но почему первый из них - ebp + 8? Поскольку, если ESP указывает на верхнюю часть стека, mov ebp, esp означает, что EBP указывает на верхнюю часть стека. Затем мы нажимаем 4 значения в стеке: eax, ebx, ecx и edx. Почему EBP + 8 указывает на первый параметр?

4b9b3361

Ответ 1

Когда функция вызывается, стек выглядит следующим образом:

+-------------+
| 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, который вы нажимаете в начале этой подпрограммы, и адрес возврата, который помещается в стек вызовом процедуры.