Assembler Simulieren



  • Hallo,

    welchen Simulator brauche ich um folgenden Assembler Code zu simulieren?

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

    MfG TheForgotten



  • TheForgotten schrieb:

    welchen Simulator brauche ich um folgenden Assembler Code zu simulieren?

    Einen der x86-32 Prozessoren Simulieren kann.



  • Kannst du mir da einen empfehlen? Ich habs schon mit ein paar versucht, die haben aber alle probleme und kennen nur "mov" anstatt "movl" ... obowhl das sicher das selbe ist würd ich doch gern nichts am Programm verändern...



  • Hä? Wills du Simulieren welche Bytes der Assembler ausgeben würde, oder was? Oder wills du einfach ne x86-CPU simulieren (dafür z.B. Bochs oder VBox)?

    [quote:1d32405c8c="TheForgotten
    "]annst du mir da einen empfehlen? Ich habs schon mit ein paar versucht, die haben aber alle probleme und kennen nur "mov" anstatt "movl" ... obowhl das sicher das selbe ist würd ich doch gern nichts am Programm verändern...Das ist jediglich AT&T-Syntax. Viele Assembler (nicht simulatoren) nehmen halt die Intel-Snytax. Aber in Maschinencode ist das das Gleiche.

    Bitte Beschreib nochmal was ein Assembler-Simulator sein soll, denn ich kapier nicht so recht was du willst.



  • Ich hab nen Code für nen Programm und soll sagen was es macht. Meiner Meinung nach kann es so eigentlich nicht funktionieren, wie es gemacht ist, da es auf die falsche Speicherzelle zugreift ...

    Eigentlich soll das Ding die Zahl 5 quadrieren. Mir ist auch noch klar, dass die 5 in eax als auch in den Stack gespeichert wird, bevor square aufgerufen wird. Nur schaut Square dann meiner Meinung nach an der falschen Stelle nach.

    Abgelegt wurde die 5 bei (x + 20), es sucht jedoch bei (x + 😎 und liegt damit meiner Meinung nach einfach 12 Felder daneben ...

    Daher wollte ich das jetzt simulieren und so erkennen, was genau Sache ist^^

    .text
    square:
    	pushl	%ebp
    	movl	%esp, %ebp
    	subl	$16, %esp
    	movl	8(%ebp), %eax
    	imull	8(%ebp), %eax
    	movl	$0, %edx
    	movl	%eax, -8(%ebp)
    	movl	%edx, -4(%ebp)
    	movl	-8(%ebp), %eax
    	movl	-4(%ebp), %edx
    	leave
    	ret
    main:
    	pushl	%ebp
    	movl	%esp, %ebp
    	andl	$-8, %esp
    	subl	$24, %esp
    	movl	$5, 20(%esp)
    	movl	20(%esp), %eax
    	movl	%eax, (%esp)
    	call	square
    	movl	%eax, 16(%esp)
    	movl	$0, %eax
    	leave
    	ret
    


  • 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