#assembly #x86
#сборка #x86
Вопрос:
aduna2:
.LFB0:
.cfi_startproc
push ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
mov ebp, esp
.cfi_def_cfa_register 5
sub esp, 16
mov DWORD PTR [ebp-4], 10
mov eax, DWORD PTR [ebp 12]
mov edx, DWORD PTR [ebp 8]
add edx, eax
mov eax, DWORD PTR [ebp 16]
add edx, eax
mov eax, DWORD PTR [ebp-4]
add eax, edx
leave
aduna:
.LFB1:
.cfi_startproc
push ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
mov ebp, esp
.cfi_def_cfa_register 5
sub esp, 28
mov DWORD PTR [ebp-4], 7
mov eax, DWORD PTR [ebp-4]
mov DWORD PTR [esp 8], eax
mov eax, DWORD PTR [ebp 12]
mov DWORD PTR [esp 4], eax
mov eax, DWORD PTR [ebp 8]
mov DWORD PTR [esp], eax
call aduna2
leave
main:
.LFB2:
.cfi_startproc
push ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
mov ebp, esp
.cfi_def_cfa_register 5
and esp, -16
sub esp, 16
mov DWORD PTR [esp 4], 6
mov DWORD PTR [esp], 5
call aduna
mov DWORD PTR [esp 4], eax
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call printf
leave
В этом коде у меня есть следующие вопросы: В основном я не могу понять, куда идет esp при замене esp 16 относительно ebp. Эти вопросы у меня есть в «adunare» и «adunare2». Я не могу понять, где это будет относительно ebp.Я не могу понять, как нарисовать стек для этой программы, потому что все мои стеки застряли, когда в «adunare2» я получаю ebp 8, ebp 12, ebp 16.Было бы полезно показать мне один, потому что я не понимаю, что происходит. И при каждом вызове туда вставляется обратный адрес? Если да в «adunare2», как вы можете получить указанные параметры, используя 8, 12, 16?
Вот код c:
#include<stdio.h>
int aduna2(int a,int b,int c)
{
int d=10;
return a b c d;
}
int aduna(int a,int b)
{
int c=7;
return aduna2(a,b,c);
}
int main()
{
printf("%dn",aduna(5,6));
}
Комментарии:
1. Эта разборка выглядит неполной. (Я бы ожидал
ret
послеleave
). Как вы это получили? Разве это не какой-то «умный» вывод дизассемблера? Используйте либо список компилятора, либо обычную разборку.
Ответ №1:
Даже из неполной разборки я думаю, что могу ответить на вопрос «что делает main со стеком перед aduna»:
main:
; store old ebp value into stack (to restore it before return)
push ebp
mov ebp, esp ; copy current value of esp to ebp
На данный момент как esp, так и ebp имеют одинаковое значение, указывая на текущую вершину стека, скажем, это 0x0054
, тогда (стековая) память выглядит следующим образом:
address | value
-----------------
0x0050 | ????
0x0054 | old_ebp <- esp/ebp pointing here
0x0058 | return address to "main" caller
0x005C | whatever was already in stack before calling main
Затем код продолжает подготавливать параметры для функции «aduna»:
and esp, -16 ; -16 = 0xFFFFFFF0 -> makes esp 16B aligned
; esp here is 0x0050
sub esp, 16 ; make room at top of stack for 16B, esp = 0x0040
; store the arguments into the stack
mov DWORD PTR [esp 4], 6 ; at 0x0044 goes value 6
mov DWORD PTR [esp], 5 ; at 0x0040 goes value 5
call aduna ; call aduna
Теперь сразу после ввода aduna ebp / esp и стековая память выглядят следующим образом:
ebp = still 0x0054, nothing did modify it
esp = 0x003C (call did pust return address at top of stack)
address | value
-----------------
0x0038 | ????
0x003C | return address to instruction after "call aduna" <- esp
0x0040 | 5
0x0044 | 6
0x0048 | ????
0x004C | ????
0x0050 | ????
0x0054 | old_ebp <- ebp pointing here
0x0058 | return address to "main" caller
0x005C | whatever was already in stack before calling main
И aduna
начните с кода пролога push ebp
mov ebp, esp
, поэтому верхняя часть стека немного изменится:
address | value
-----------------
0x0038 | 0x0054 <- both esp and ebp pointing here (= 0x0038)
0x003C | return address to instruction after "call aduna"
0x0040 | 5
0x0044 | 6
Таким образом, mov eax, DWORD PTR [ebp 12]
будет получен адрес 0x0044 (0x38 0x0C = 0x44), там хранится 6. ebp 8
указывает на значение 5. Остальные esp
/ ebp
комбинации в aduna
пунктах ниже этого, в локальные переменные (которые находятся в «стековой» части памяти), которые я не собираюсь описывать, как только вы пойметеэта начальная часть, вы должны быть в состоянии расшифровать и остальную ее часть.
Для leave
проверки руководства по набору инструкций (оно меняет оба esp
и ebp
). И отсутствие ret
тоже важно, esp
оно также меняется.