Assembler, was genau bedeuten diese Anweisungen

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

Der Eisvogel

Betreff: Assembler, was genau bedeuten diese Anweisungen

BeitragSa, Apr 07, 2012 13:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich bin mal wieder am verzweifeln was Assembler angeht. Ich habe ein Funktion in Assembler mit folgenden Startanweisungen:
Code: [AUSKLAPPEN]
push ebp
mov ebp,esp
sub esp,10h
push ebx
push esi
push edi
push 00


Die Endanweisungen sind folgende:
Code: [AUSKLAPPEN]
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 8


Nach den Startanweisungen erfolt ein cdecl call zu einer Funktion mit einem Parameter (push 00). Mir erschließt sich der Sinn der drei davor erfolgenden Push-Anweisungen und den drei am Ende nicht so wirklich. Was genau bewirken diese und was bewirkt das "sub esp,10h" am Anfang? Also was genau ist der Sinn dahinter? Mein erster Gedanke war, dass die Register gesichert werden, was mir aber irgendwie schleierhaft vorkommt.

Ich hoffe ich steh nicht irgendwie auf dem Schlauch. Freue mich auf euere Hilfe.

MfG
Der Eisvogel
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Nicdel

BeitragSa, Apr 07, 2012 17:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Soweit ich ASM verstehe wird zuerst der stack pointer um 0x10 verschoben (also 16), danach werden 3 register gesichert. Der 4. push ist dann der Parameter für die Funktion und liegt durch das Verschieben des stack pointers (esp) jetzt genau an der ersten Stelle, wo es als einziges von der Funktion verwendet wird. Danach werden die ursprünglichen Register und der alte stack pointer wiederhergestellt. Ist also so ne Art Sicherungsmaßnahme, ähnlich wie pushad/popad.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Der Eisvogel

BeitragSa, Apr 07, 2012 17:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Aber warum finde ich das nur in dieser einen Funktion und nirgends anders? Das muss doch noch irgendeinen tiefgründigeren Sinn haben oder nicht?
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Nicdel

BeitragSa, Apr 07, 2012 17:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Eisvogel hat Folgendes geschrieben:
Aber warum finde ich das nur in dieser einen Funktion und nirgends anders? Das muss doch noch irgendeinen tiefgründigeren Sinn haben oder nicht?


Evtl. werden die Register in der Funktion nach den Startanweisungen verändert, müssen aber danach wieder im Originalzustand vorliegen.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Thunder

BeitragSa, Apr 07, 2012 17:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich denke, wieso das so ist, kann man dir nicht erklären, solange man den Kontext nicht kennt. Der Code ist handgeschrieben oder? Also nicht von einem Compiler generiert.
Es wäre außerdem gut zu wissen:
a) was noch in der Funktion steht.
b) welche Funktion aufgerufen wird und eventuell der Code dieser Funktion.
c) der Kontext. Welcher Code ruft die gefragte Funktion auf.

Denn ich denke, was im Code passiert, hast du verstanden - wieso es passiert, kann ich mir/dir aber, mit der Informationsbasis, nicht erklären.

Der Eisvogel

BeitragSa, Apr 07, 2012 18:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Code kommt aus CheatEngine direkt. Wenn ich mich vertippt habe ist das ein Versehen.

Der gesamte Code der Funktion wäre folgender:
Code: [AUSKLAPPEN]
push ebp
mov ebp,esp
sub esp,10
push ebx
push esi
push edi
push 00
call dword ptr [manager+BDB8]
mov ecx,[ebp+0C]
mov edx,[ebp+08]
add esp,04
mov [ebp-08],eax
lea eax,[ebp-04]
push eax
mov eax,[manager+BCD4]
push ecx
push edx
mov ecx,[eax]
call dword ptr [manager+C3EC]
test eax,eax
je D3
mov ecx,[ebp-04]
or esi,FF
fild dword ptr [ecx+00000384]
mov edx,[ecx+00000394]
mov eax,[ecx]
mov edi,[ecx+0000038C]
mov [ebp-10],edx
fstp dword ptr [ebp+08]
fild dword ptr [ecx+00000388]
fstp dword ptr [ebp+0C]
call dword ptr [eax+5C]
test eax,eax
mov eax,[ebp-04]
je 84
mov ecx,[eax+000007A4]
mov esi,[eax+00000784]
mov ebx,[eax+000007A0]
xor edi,edi
mov [ebp-0C],ecx
jmp 87
mov ebx,[ebp+0C]
mov ecx,[ebp-08]
push eax
mov edx,[ecx]
call dword ptr [edx+00000290]
mov eax,[manager+BCD4]
mov ecx,[eax]
add ecx,0010A3F8
call dword ptr [manager+C33C]
mov eax,[ebp+08]
mov edx,[ebp+0C]
cmp esi,FF
je BB
mov ecx,[ebp-0C]
push FF
push ecx
push ebx
push esi
jmp C5
mov ecx,[ebp-10]
push ecx
push 00
push 00
push 00
mov ecx,[ebp-04]
push edi
push 00
push edx
push eax
call dword ptr [manager+C418]
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 0008


Was da alles passiert ist mir klar. Der Aufruf dieser Funktion erfolgt von vielen verschieden Stellen, an denen ich bisher keine gemeinsamkeit feststellen konnte. Auch sind Anweisungen betreffend der drei Register sehr verstreut weit entfernt vom eigentlichen Funktionaufruf zu finden. Nach dem Funktionsaufruf werden diese jedoch nicht mehr verwendet ohne vorher neu beschrieben zu werden.

Der gesamte Code, also der in denen die Funktion aufgerufen wird ist zu groß, als dass es sich lohnen würde sich da als Dritter einzulesen. Eigentlich hatte ich gehofft, dass es irgendetwas Assembler typisches ist, was man halt so macht.

MfG
Der Eisvogel
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Thunder

BeitragSa, Apr 07, 2012 18:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Das "sub esp, 10h" ist wirklich für lokale Variablen da. Was gespeichert wird, weiß ich nicht, aber es sind definitiv lokale Variablen der Funktion.
Die Register werden gesichert, weil sie verwendet werden und afaik ist es üblich, dass alle Register (außer eax, ecx und edx) - wenn sie von der Funktion verändert werden - vorher gesichert werden, damit sich die aufrufende Funktion darauf verlassen kann, dass ihr Wert erhalten bleibt. Wenn sie danach wirklich nicht gebraucht werden, hätten diese Zeilen wegoptimiert werden können - vielleicht hat der Compiler es nicht geschafft (wenn der Code aus der Cheatengine ist, nehme ich an, dass er doch von einem Compiler stammt).
Das "ret 8" heißt wohl, dass deine Funktion mit stdcall convention aufgerufen wird und sie selbst ihre Parameter vom Stack nimmt (die eine Größe von 8 Byte haben).
Insofern sind diese Sachen etwas typisches, liefern aber auch nur sehr oberflächliche Informationen.
Vielleicht hilft es dir trotzdem.

Der Eisvogel

BeitragSa, Apr 07, 2012 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
OK, danke. Das die Register gesichert werden wusste ich auch mal xD. Jedoch ist es mir nie so aufgefallen, da es im Rest des Codes irgendwie im Verlaufe der Funktion selbst geschehen ist und nicht immer auf einem Haufen stand. Schon lustig irgendwie. Damit hat sich mein Verständnis-Problem dann wohl geklärt.
Vielen Dank!

MfG
Der Eisvogel
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Noobody

BeitragSo, Apr 08, 2012 9:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Wichtig zu wissen: Register bx, si und di sind "Callee-Save", sprich, die aufgerufene Funktion muss sicherstellen, dass sie nach einem Return die gleichen Werte haben wie vor dem Aufruf. ax, dx und cx sind hingegen "Caller-Save", d.h. die aufrufende Funktion muss die Werte sichern, falls sie an deren Inhalt noch interessiert ist; die aufgerufene Funktion darf diese Register frei verändern, ohne sie sichern zu müssen.

In diesem Fall modifiziert die Funktion tatsächlich die drei Callee-Save Register, daher muss sie auch deren Werte am Anfang der Funktion mit einem push retten und vor dem return wieder mit einem pop wiederherstellen.

Die "sub esp, 10h" setzt nur das lokale Stackframe auf. Diese Anweisung, zusammen mit "push ebp" "mov ebp, esp", wirst du praktisch in jeder Compiler-generierten Funktion finden (ausser, dein Compiler benutzt die red zone als Optimierung).
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group