сборка x86 «декомпиляция»

У меня проблемы с пониманием этой сборки кода x86 (AT&Обозначение T). Мне нужно уметь это понимать (написать функцию C ++, скомпилированную с этим кодом) и выполнить аналогичные упражнения на экзамене.
Можете ли вы объяснить мне, какая часть делает, что и что такое конвенция?

f:
pushl %ebp ; 1
movl %esp, %ebp; 2
pushl %ebx ; 3
subl $36, %esp; 4
movl 8(%ebp), %edx ; 5
movl 12(%ebp), %eax ; 6
movl (%eax), %eax ; 7
movl %edx, 8(%esp) ; 8
leal 16(%ebp), %edx ; 9
movl %edx, 4(%esp) ; 10
movl %eax, (%esp) ; 11
call f; 12
movl %eax, -12(%ebp) ; 13
movl 16(%ebp), %edx ; 14
movl 12(%ebp), %eax ; 15
movl %edx, (%eax) ; 16
movl 12(%ebp), %eax ; 17
movl (%eax), %edx ; 18
movl -12(%ebp), %eax ; 19
movl %edx, 8(%esp) ; 20
leal 8(%ebp), %edx ; 21
movl %edx, 4(%esp) ; 22
movl %eax, (%esp) ; 23
call f; 24
movl %eax, %ebx; 25
movl 16(%ebp), %edx ; 26
movl -12(%ebp), %eax ; 27
movl %edx, 8(%esp) ; 28
movl 12(%ebp), %edx ; 29
movl %edx, 4(%esp) ; 30
movl %eax, (%esp) ; 31
call f; 32
movl %eax, %edx; 33
movl 16(%ebp), %eax ; 34
movl %edx, 8(%esp) ; 35
leal 8(%ebp), %edx ; 36
movl %edx, 4(%esp) ; 37
movl %eax, (%esp) ; 38
call f; 39
movl %ebx, 8(%esp) ; 40
leal -12(%ebp), %edx ; 41
movl %edx, 4(%esp) ; 42
movl %eax, (%esp) ; 43
call f; 44
addl $36, %esp; 45
popl %ebx ; 46
popl %ebp ; 47
ret; 48

Здесь нет прыжков, но есть несколько «call f», означает ли это, что существует бесконечный цикл?

-2

Решение

Ниже немного, чтобы помочь вам начать работу.

Шаг 1. Разделите код на логические куски. Ключевыми вещами, которые нужно искать для идентификации логических порций, являются пролог стека и код эпилога, вызовы функций, операторы ветвления и адреса, идентифицированные операторами ветвления.

Шаг 2. Сделайте заметки о том, что делает каждый кусок.

Например …

f:
pushl %ebp
movl %esp, %ebp      ; Create the stack frame
pushl %ebx           ; and save non-volatile register EBX
subl $36, %esp       ; Carve space for 9 32-bit words on the stack

; Notes: 8(%ebp) is the address for the 1st parameter
;       12(%ebp) is the address for the 2nd parameter
;       16(%ebp) is the address for the 3rd parameter
;
; Anything addresses as -#(%ebp) will be a stack variable
; local to this function.
;
; Anything addressed as #(%esp) will be used to pass parameters
; to the sub-function.  The advantage of doing it this way is that
; parameters passed to the sub-function do not have to be popped
; after every call to a sub-function.

movl 8(%ebp), %edx         ; EDX = 1st parameter
movl 12(%ebp), %eax        ; EAX = 2nd parameter
movl (%eax), %eax          ;       The 2nd parameter is a pointer!
movl %edx, 8(%esp)         ; Pass EDX as 3rd parameter to sub-function
leal 16(%ebp), %edx        ; EDX = address of 3rd parameter to this function
movl %edx, 4(%esp)         ;       Passing it as 2nd parameter to sub-function
movl %eax, (%esp)          ; Pass EAX as 3rd parameter to sub-function
call f                     ; Call sub-function
movl %eax, -12(%ebp)       ; Save return value to local stack variable

; More Notes:
; I am guessing that this bit of decompiled code was an object file.
; Experience has shown me that when the address sub-functions used by
; CALL are all the same (and match the address of the calling function)
; this is often due to decompiling an object file as opposed to an
; executable.  If however, the sub-function address truly is '0xf', then
; this will be a recursive routine that will blow the stack as there is
; no exit condition.

movl 16(%ebp), %edx    ; EDX: 3rd parameter passed to function
;      likely modified by previous CALL
movl 12(%ebp), %eax    ; EAX: 2nd parameter passed to function
movl %edx, (%eax)      ; Save EDX to the location pointed to by the 2nd parameter
movl 12(%ebp), %eax    ; EAX: 2nd parameter passed to function (recall it's a ptr)
movl (%eax), %edx      ;    ... and so on ...
movl -12(%ebp), %eax
movl %edx, 8(%esp)
leal 8(%ebp), %edx)
movl %edx, 4(%esp)
movl %eax, (%esp)
call f
movl %eax, %ebx

movl 16(%ebp), %edx
movl -12(%ebp), %eax
movl %edx, 8(%esp)
movl 12(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call f
movl %eax, %edx

movl 16(%ebp), %eax
movl %edx, 8(%esp)
leal 8(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call f
movl %ebx, 8(%esp)

leal -12(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call f

addl $36, %esp             ; Reclaim that carved stack space
popl %ebx                  ; Restore the non-volatile register EBX
popl %ebp                  ; Restore to the caller's stack frame
ret                        ; Return

Я оставляю все остальное для вас. Я надеюсь, что это поможет вам.

2

Другие решения

Эта функция f является рекурсивной функцией без завершения рекурсии. Что-то вроде

void f(int a, int b, int c)
{
f(a,b,c);
//....
}

Прекратите оценивать дизассемблирование, так как не стоит получать такой плохой код на любом языке высокого уровня.

0

Я пришел к решению:

int f (int i, int* j, int k) {
int n = f(*j, &k, i);
*j = k;
f( f(n, &i, *j), &n, f(k, &i, f(n, j, k)) );
return 0;
}

при компиляции моего кода
g ++ -m32 -S a.cpp

Я получаю следующий код сборки:
_Z1fiPii:
.LFB971:
.cfi_startproc
.cfi_personality 0, __gxx_personality_v0
.cfi_lsda 0, .LLSDA971
pushl% ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl% esp,% ebp
.cfi_def_cfa_register 5
pushl% ebx
Subl $ 36,% esp
.cfi_offset 3, -12
MOVL 8 (% EBP),% EDX
MOVL 12 (% EBP),% EAX
MOVL (% eax),% eax
movl% edx, 8 (% esp)
leal 16 (% ebp),% edx
movl% edx, 4 (% esp)
movl% eax, (% esp)
.LEHB0:
позвонить _Z1fiPii
movl% eax, -12 (% ebp)
MOVL 16 (% EBP),% EDX
MOVL 12 (% EBP),% EAX
movl% edx, (% eax)
MOVL 16 (% EBP),% EDX
MOVL -12 (% ebp),% eax
movl% edx, 8 (% esp)
MOVL 12 (% EBP),% EDX
movl% edx, 4 (% esp)
movl% eax, (% esp)
позвонить _Z1fiPii
MOVL 16 (% EBP),% EDX
movl% eax, 8 (% esp)
leal 8 (% ebp),% eax
movl% eax, 4 (% esp)
movl% edx, (% esp)
позвонить _Z1fiPii
movl% eax,% ebx
MOVL 12 (% EBP),% EAX
movl (% eax),% edx
MOVL -12 (% ebp),% eax
movl% edx, 8 (% esp)
leal 8 (% ebp),% ecx
movl% ecx, 4 (% esp)
movl% eax, (% esp)
позвонить _Z1fiPii
movl% ebx, 8 (% esp)
leal -12 (% ebp),% edx
movl% edx, 4 (% esp)
movl% eax, (% esp)
позвонить _Z1fiPii
.LEHE0:
movl $ 0,% eax
jmp .L5
.L4:
movl% eax, (% esp)
.LEHB1:
вызвать _Unwind_Resume
.LEHE1:
.L5:
addl $ 36,% esp
popl% ebx
.cfi_restore 3
popl% ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
RET
.cfi_endproc

Это эквивалентно тому, который был вставлен раньше?

0
По вопросам рекламы [email protected]