Assembler Simulieren



  • Wenn du das durchgehen möchtest, dann nimm einen Debugger und lass das Programm im Singel-Step-Modus durchlaufen. Dann kannst du den Stack und die Register durchcheken.



  • Und welchen lad ich mir da am besten runter? Ich hab noch null Ahnung von der Sache 😕



  • Ich benutz den Debugger von VisualStudio, da ich in der Regel nur meinen Code debugge und keine externen Programme. Der kann sich aber auch an Prozesse anhängen.
    Theoretisch hat Windows auch einen internen Debugger, das CMD-Command "debug". Als externen Debugger gibts z.B. OllyDbg.



  • Danke, danke^^ Jetzt müsst ich nur noch wissen, wie ich aus meinen 20 Zeilen eine *.exe Datei mache?

    Wenn ich das bisher mit Programmen ausm Web versucht hab, konnten die immer mit ".text" und mit "leave" nichts anfangen :S



  • Um aus deinem Asm-Code ein Programm zu machen benötigst du Assembler + Linker. Normalerweise würde ich hier auf NASM verweisen, aber der kennt nur seine Intel-Syntax.
    Für dich dürfte "as" aus dem GCC-Toolset als Assembler taugen und der "ld" als Linker, welcher ebenfalls beim GCC dabei sind.



  • Ich hab jetzt mal versucht das in intel Code umzuwandeln

    .text
    
    main:
    	push	ebp
    	mov	ebp, esp
    	and	esp, 8
    	sub	esp, 24
    	mov	[esp+20], 5
    	mov	eax, [esp+20]
    	mov	esp, eax
    	call	square
    	mov	[esp+16], eax
    	mov	eax, 0
    ;	leave
    	ret
    
    square:
    	push	ebp
    	mov	esp, ebp 
    	sub	 esp, 16
    	mov	 eax, [ebp+8]
    	imul	 eax, [ebp+8]
    	mov	edx, 0
    	mov	[ebp-8], eax 
    	mov	[ebp-4], edx
    	mov	eax, [ebp-8]
    	mov	edx, [ebp-4]
    ;	leave
    	ret
    

    Da wird dann aber ständig Speichterunterlauf/überlauf gemeckert ...



  • Wobei ich eigentlich nur zwei Fragen habe ...

    Was macht folgender Teil und brauche ich ihn wirklich?

    mov    [ebp-8], eax
        mov    [ebp-4], edx
        mov    eax, [ebp-8]
        mov    edx, [ebp-4]
    

    Und, wie kommt die "5" in diese Speicherzelle?

    [ebp+8]
    

    Ohne, dass die "5" in dieser Zelle ist, macht

    mov eax, [ebp+8]
    imul eax, [ebp+8]

    nämlich keinen Sinn ...



  • Versuch lieber das Original zu verstehen, dir sind da beim Übersetzen anscheinend ein paar Fehler passiert...



  • Beim Original wird ja in

    movl    $5, 20(%esp)
    

    die 5 auf den Stack gespeichert.
    Wie kommt es jetzt, dass man eben diese später über

    8(%ebp)
    

    erreicht?

    Und wofür ist der

    movl    %eax, -8(%ebp)
        movl    %edx, -4(%ebp)
        movl    -8(%ebp), %eax
        movl    -4(%ebp), %edx
    

    Block ... wird hier einmal in die eine Richtung gespeichert und dann das selbe noch einmal in die andere?



  • ; Funktion: int square(int x)
        pushl    %ebp            ; stack frame
        movl    %esp, %ebp       ; 
        subl    $16, %esp        ; lokale Variablen (werden nicht benötigt!)
    
        movl    8(%ebp), %eax    ; eax = Argument = x
        imull    8(%ebp), %eax   ; eax = eax * x = x * x
        movl    $0, %edx         ; edx = 0
    
        movl    %eax, -8(%ebp)   ; Sinnlos
        movl    %edx, -4(%ebp)   ; 
        movl    -8(%ebp), %eax   ; 
        movl    -4(%ebp), %edx   ; 
        leave 
        ret 
    
        ; Programmeintritspunkt
    main: 
        pushl    %ebp            ; stack frame
        movl    %esp, %ebp       ;
        andl    $-8, %esp        ; lokale Variablen: align 8 , size = 24 Byte
        subl    $24, %esp        ; Auserdem wird hier Platz für das Funktionsargument gemacht  (square(int x))
    
        movl    $5, 20(%esp)     ; Verschwendung -> mov $5,%eax
        movl    20(%esp), %eax   ; 
    
        movl    %eax, (%esp)     ; Argument auf den Stack (=5)
        call    square
        movl    %eax, 16(%esp)   ; Ergebniss in lokaler Variable speichern
    
        movl    $0, %eax         ; Rückgabewert = 0
        leave 
        ret
    


  • Die 5 wird nicht nur in [esp+20] gespeichert, sondern danach nach eax geschoben und von dort nach [esp]. Dann gibts einen call und ein push, d.h. esp wird um 8 erniedrigt. Dann wird esp nach ebp kopiert und auf [ebp+8] zugegriffen, und das ist natürlich die gleiche Speicherstelle wie die, die vorher mal [esp] war.

    Zu der zweiten Frage: Keine Ahnung. Das Programm sieht aus wie von einem Compiler ohne Optimierung erzeugt. Da wird wohl das Ergebnis nochmal in eine lokale Variable geschrieben, obwohl die gar nicht mehr gebraucht wird.



  • Danke, danke^^



  • Wenn's dich interessiert, es dürfte sich dabei um das unoptimierte Kompilat von etwas ähnlichem wie diesem C-Programm handeln:

    long long square(int v)
    {
      long long ret=v*v;
      return ret;
    }
    
    int main(void)
    {
      int a=5;
      int s=square(a);
      return 0;
    }
    


  • Man könnte das sinnvollerweise mit dem gas und gdb unter Linux untersuchen, aber gerade um des Verständniswillens würde ich vorschlagen, das ganze mit Bleistift und kariertem Papier(Speicherbereich) aufzuzeichnen.

    Dem Stackpointer kann man die Adresse FFFFFFFFh geben, und -8 für den AND-Befehl wäre FFFFFFF8h. Sollte der Stackpointer zufälligerweise auf FEEDDEADh zeigen, dann wird nach dem AND Befehl FEEDDEA8h daraus.


Anmelden zum Antworten