2016-10-07 7 views
0
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が相対的にebpに相対的なときにどこに行くのかわかりません。この質問は私が "adunare"と "adunare2"に持っています。私はそれが相対的にどこにebpになるのか分かりません。私のスタックはすべて "adunare2"の時にスタックしているので、私はebp + 8、ebp + 12、ebp + 16.を取得します。何が起こっているのか分からないので、私に1つを示すことは役に立ちます。そして、それぞれの呼び出しでそこに戻りアドレスが挿入されますか? "adunare2"で "yes"の場合、+ 8、+ 12、+ 16を使って上記のパラメータを得る方法は?アセンブリスタック3の機能

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:でも私は「何aduna前にスタックしてメインません」と答えることができると思い不完全な分解から

#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("%d\n",aduna(5,6)); 
} 
+0

その分解は不完全に見えます。 (私は休暇の後に 'ret'を期待します)。どうやって手に入れたの?それはいくつかの "スマート"逆アセンブラの出力ですか?コンパイラリストまたは通常の逆アセンブリのいずれかを使用します。 – Ped7g

答えて

0

:ここ

は、Cコードでありますと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" 機能のためのパラメータを準備するために引き続き:

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開始:右aduna EBP/ESPとスタックメモリを入力した後

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 

を今はこのようになります

address | value 
----------------- 
0x0038 | 0x0054 <- both esp and ebp pointing here (= 0x0038) 
0x003C | return address to instruction after "call aduna" 
0x0040 | 5 
0x0044 | 6 
:プロローグコード push ebp mov ebp, espので、スタックの最上位ビットが変化すると

だからmov eax, DWORD PTR [ebp+12]はアドレス0x0044(0x38 + 0x0C = 0x44)をフェッチし、そこに6が格納されます。esp/ebpの残りの部分は、adunaの範囲内のこの部分の残りをローカル変数に置き換えます( "stack"部分私はこの最初の部分を理解すると、残りの部分も解読できるはずです。

leaveについては、命令セットマニュアル(espebpの両方を変更します)を確認してください。そして、retの欠落も重要です。espも同様です。