Assembler und Funktionsaufrufe



  • Hallo! ­čÖé

    Ich besch├Ąftige mich im Moment etwas mit Assembler und habe gerade einige kleine Schwierigkeiten, den generellen Ablauf eines Funktionsaufrufes zu verstehen:

    Hier der C-Code:

    void test_function(int a, int b, int c, int d) {
    
    int flag;
    char buffer[10]
    
    flag = 31337;
    buffer[0] = 'A';
    
    }
    
    int main() {
    
        test_fuction(1,2,3,4);
    
    }
    

    Der Assembler sieht so aus:

    push ebp
    mov ebp, esp
    sub esp,0x18
    and esp,0xffffffff0
    mov eax,0x0
    sub esp,eax
    mov DWORD PTR [esp+12], 0x4
    mov DWORD PTR [esp+12], 0x3
    mov DWORD PTR [esp+12], 0x2
    mov DWORD PTR [esp+12], 0x1
    call <test_function>
    

    Dann der Code f├╝r den Funktionsaufruf:

    push ebp
    mov ebp, esp
    sub esp,0x28
    mov DWORD PTR [ebp-12], 0x7a69 ;das ist halt die 31337 in hexadezimal
    mov BYTE PTR [ebp-40], 0x41    ;ist das A in ASCII
    leave
    ret
    

    So, was ich nicht genau verstehe ist, warum macht man:

    and esp,0xffffffff0
    mov eax,0x0
    sub esp,eax
    

    Warum f├╝hrt man auf dem esp ein logisches und mit dieser Zahl aus und warum schiebt man dann eine 0 ins eax und zieht diese von esp wieder ab?

    Zweitens:

    sub esp,0x28
    mov DWORD PTR [ebp-12], 0x7a69 ;das ist halt die 31337 in hexadezimal
    mov BYTE PTR [ebp-40], 0x41    ;ist das A in ASCII
    

    Hier werden ja durch

    sub esp,0x28
    

    40 Byte resaviert. Warum 40? Der Int und die 10 char's des Arrays sind doch insgesamt nur 14 Byte, oder?
    Und warum schiebe ich die 0x7a69 ab der Stelle [ebp-12] in den RAM und nicht ab Stelle [ebp-4]? Weil ich mache ja "mov ebp, esp", d.h. ich setze ebp auf den zu dem Zeitpunkt aktuellen ESP. Jetzt zeigte der ESP ja zu dem Zeitpunkt auch nat├╝rlich auf das Ende des Stacks was hier der Wert ist, nachdem ich

    push ebp
    

    ausgef├╝hrt habe. Das Hei├čt der ESP zeigt doch nach

    push ebp
    

    praktisch auf die Stelle hinter dem gesicherten EBP? Auf jeden Fall w├╝rde ich die 0x7a69 halt dann ab [ebp] schreiben, halt direkt nach dem gesicherten EBP.
    Und daher auch, warum schreibe ich das 'A' ab ebp-40?

    Kann mir das bitte jemand erkl├Ąren? ­čÖé

    Danke!


  • Mod

    CCat schrieb:

    Der Assembler sieht so aus:

    push ebp
    mov ebp, esp
    sub esp,0x18
    and esp,0xffffffff0
    mov eax,0x0
    sub esp,eax
    mov DWORD PTR [esp+12], 0x4
    mov DWORD PTR [esp+12], 0x3
    mov DWORD PTR [esp+12], 0x2
    mov DWORD PTR [esp+12], 0x1
    call <test_function>
    

    Ich nehme mal an, dass das kein copy&paste ist. Die Adressen der Funktionsargumente k├Ânnen so ja offensichtlich nicht stimmen.

    Mit welchem Compiler auf welchem System mit welchen Compiler-Einstellungen wurde dieser Code erzeugt?

    CCat schrieb:

    So, was ich nicht genau verstehe ist, warum macht man:

    and esp,0xffffffff0
    mov eax,0x0
    sub esp,eax
    

    Warum f├╝hrt man auf dem esp ein logisches und mit dieser Zahl aus und warum schiebt man dann eine 0 ins eax und zieht diese von esp wieder ab?

    *Man* macht nicht, der Compiler hat sich in diesem speziellen Fall dazu entschieden, diesen Code zu erzeugen. Das and d├╝rfte dazu dienen, den Stack auf 16 Byte auszurichten - gcc macht das z.B. einmalig in main, um dann ohne weiteren Aufwand mit automatischen SSE-Variablen umgehen zu k├Ânnen. Der Zweck des mov eax+sub erschlie├čt sich daraus nicht; es k├Ânnte sich evtl. um Padding handeln, um Debugging zu erleichtern.

    CCat schrieb:

    Zweitens:

    sub esp,0x28
    mov DWORD PTR [ebp-12], 0x7a69 ;das ist halt die 31337 in hexadezimal
    mov BYTE PTR [ebp-40], 0x41    ;ist das A in ASCII
    

    Hier werden ja durch

    sub esp,0x28
    

    40 Byte resaviert. Warum 40? Der Int und die 10 char's des Arrays sind doch insgesamt nur 14 Byte, oder?
    Und warum schiebe ich die 0x7a69 ab der Stelle [ebp-12] in den RAM und nicht ab Stelle [ebp-4]?

    Der Compiler ist nicht gezwungen, Variablen direkt aufeinander folgend anzuordnen. Insbesondere um Arrays herum wird bei ausgelassener Optimierung gerne etwas Platz gelassen, um Bereichs├╝berschreitungen erkennen zu k├Ânnen.


Log in to reply