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 über8(%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.