Hallo Markus,
Es passt zwar nicht unbedingt hier rein, aber ich bin sicher, dass mich jemand diesbezüglich aufklären kann.
ich will's versuchen. ;-)
Lass mich zuerst noch mal laut denken: Im Lunux-Kernel ruft int 0x80 etliche Systemfunktionen auf, in eax wird die Funktionsnummer angegeben. Funktion #4 scheint eine Stringausgabe zu sein, bei der in ebx der Filehandle (hier 1=stdout), in ecx ein Zeiger auf den String und in edx die Länge des Strings übergeben wird.
Also los.
segment .code
msg1 db "Message 1", 10
len1 equ $-msg1
msg2 db "Message 2", 10
len2 equ $-msg2segment .text
global _start_start:
mov eax, msg1
push eax ; lege einen Zeiger auf msg1 auf dem Stack ab
mov eax, msg2
push eax ; lege einen Zeiger auf msg2 auf dem Stack ab
Bis hier war's Vorgeplänkel, das mit dem eigentlichen Funktionsaufruf nichts zu tun hat.
mov eax, 4 ; Funktionsnummer
mov ebx, 1 ; File-Handle (stdout)
mov ecx, [esp+4] ; Zeiger auf String (*)
mov edx, len1 ; Stringlänge
int 0x80 ; Funktionsaufruf
mov eax, 1 ; Funktionsummer für "Prozess beenden"
int 0x80 ; Funkion ausführen
Eines verstehe ich nicht.
Eines verstehe _ich_ nicht: Wozu legst du erst zwei Werte auf den Stack? Das erscheint mir völlig zweckfrei, und in diesem Fall unnötig. Da die beiden Werte nie wieder vom Stack abgeräumt werden, ist das genaugenommen sogar ein schwerwiegender Fehler, der nur deshalb keine Schutzverletzung (o.ä.) verursacht, weil das Programm danach sowieso beendet wird, ohne nochmal auf Werte von Stack (z.B. Rücksprungadressen) zurückzugreifen.
Okay, zurück zur eigentlichen Frage: Nehmen wir mal an, der Stackpointer esp habe zu Beginn dieses Codestücks den Wert 00001000h.
Bei einem push-Befehl wird erst der Stackpointer um die Anzahl der gepushten Bytes vermindert (hier 4, den es wird ein 32bit-Register gepusht), dann der gepushte Wert an die Adresse geschrieben, auf die der Stackpointer nun zeigt.
Nach den beiden push-Befehlen haben wir also folgende Bestandsaufnahme:
esp = 00000FF8h
Stack: 00001000: [Inhalt unbekannt]
00000FFC: Zeiger auf msg1
00000FF8: Zeiger auf msg2
So. Wenn du jetzt 'mov ecx,[esp+4] ausführst, dann lädst du den Wert, an der Speicheradresse esp+4, also im Moment 00000FFCh steht, ins ecx-Register. Das ist "zufällig" genau der Zeiger auf msg1, den du vorher per push-Befehl dort abgelegt hast.
So isoliert erscheint mir dieses Code-Beispiel aber ziemlich sinnlos, vom vorher beschriebenen Stackfehler ganz abgesehen. Hast du das eventuell aus einem größeren Zusammenhang gerissen oder Teile herausgekürzt, ohne genau zu wissen, was du tust?
Ich bin mal gespannt, wo mein Denkfehler ist.
Ich hoffe, du erkennst ihn jetzt.
So long,
Martin
Wenn du beim Kochen etwas heißes Wasser übrig hast, friere es ein.
Heißes Wasser kann man immer gebrauchen.