Frage zu Register
-
mov [ebx] , 2 ; Was bedeuteten die Klammern um EBX ?
-
[ebx] => Speicherstelle adressiert durch den Inhalt von ebx. Bei deinem Beispiel ist allerdings nicht eindeutig um welchen Datentyp es sich handelt (byte,word,dword)
-
Es muss geklärt werden, ob
- ebx überhaupt ein Register ist. Könnte eine Variable sein, ist daher ein Displacement und es wird direkte Adressierungsart verwendet
- ebx Basisregister ist
- ebx Indexregister ist
- ebx einfach nur ein Register ist. Die Konstante 2 ist vielleicht ein Displacement und man muss den Befehl von links nach rechts lesen: Speichere Register ebx an der Adresse 2
-
was soll das für ein Assembler sein, bei dem man Variabeln wie Register benennen kann? Und was für ein unterschied macht es, ob EBX als Index- oder Basisregister verwendet wird?
-
abc.w schrieb:
Es muss geklärt werden, ob
- ebx überhaupt ein Register ist. Könnte eine Variable sein, ist daher ein Displacement und es wird direkte Adressierungsart verwendet
- ebx Basisregister ist
- ebx Indexregister ist
- ebx einfach nur ein Register ist. Die Konstante 2 ist vielleicht ein Displacement und man muss den Befehl von links nach rechts lesen: Speichere Register ebx an der Adresse 2
Ist es wieder einmal diese Zeit des Jahres, in der du ohne Ruecksicht auf Verluste jeden 2. Thread kapern willst, um jedem den es nicht interessiert die Vorzuege des gas (diesmal implizit ueber die Syntax) einzutrichtern?
OP hat gefragt; masm hat eine allgemein ausreichende Antwort gegeben. Deine Fragen tragen so allein an dieser Stelle bestenfalls zur Verwirrung bei.
Falls du mal wieder die AT&T vs. Intel diskutieren willst => bitte neuen Thread aufmachen.
-
oops sry da fehlte noch was^^
Ich glaub so sah das aus was ich mal irgendwo gesehen habe und nicht genau wusste was es war.
Angenommen die Offset Adresse von var wäre:
12FF80mov edx,offset var ; edx = 12FF80 mov ebx,edx ; ebx = 12FF80 mov word ptr [ebx] , 2h ; ebx= ? [ebx]= ?
Also offset Adresse von var nach edx.
Dann Adresse die Offset Adresse ( die nun im edx liegt ) nach ebx kopieren.Aber was heisst das hier jetzt genau:
[ebx] => Speicherstelle adressiert durch den Inhalt von ebx.Welche Speicherstelle wird hier mit dem Inhalt von ebx adressiert. O_o
Ich hab gerade nochmal versucht das mit einem Debugger nachzuvollziehen jedoch ohne Erfolg.
-
Hier konnte ich rausfinden das:
mov eax, dword ptr [var]
das selbe ist wie
mov eax, dword ptr varAber wenn ein Register umklammert ist dann weiss ich einfach nicht was da passiert.
Wieso krieg ich das nicht hin ! >_<
zz db "abc" ,0 var dw 3 , 0 .code start: xor eax,eax xor ebx,ebx mov eax, dword ptr [var] xor eax,eax mov eax, dword ptr var
-
Ganz allgemein gilt bei Intel-Syntax: Eckige Klammern um einen Ausdruck bedeuten einen Speicherzugriff (RAM). Der Ausdruck in den eckigen Klammern ist dann allgemein die Speicher-Adresse, auf die zugegriffen wird.
Wenn du sowas wiemov eax, [ebx]
hast, dann wird eben der Wert in ebx als Offset-Adresse hergenommen, der Wert an dieser Adresse ausgelesen und in eax gespeichert.
ebx wird hier also als Pointer benutzt.Falls dir ein Bezug zu C weiter hilft:
mov eax, ebx entspricht eax = ebx
mov eax, [ebx] entspricht eax = *ebxbob- schrieb:
mov eax, dword ptr [var]
das selbe ist wie
mov eax, dword ptr varDas stimmt so nicht ganz.
Die Sache ist leider nicht sehr uebersichtlich... Aber ich versuchs mal:
Das erste beschreibt explizit einen Speicherzugriff in MASM-artiger Syntax.
Das zweite beschreibt scheinbar einen Zugriff auf eine "Variable" in MASM-artiger Syntax, jedoch zusaetzlich mit einer Angabe des Datentyps.
AFAIR unterstuetzt MASM grob folgendes Konzept von Variablen: Das sind erstmal normale Labels mit einem Stueck reserviertem (ggF. initialisiertem) Speicher. Allerdings kann man auf solche Variablen (dh. auf den Speicher) nun zugreifen, ohne Eckige Klammern zu verwenden oder den Datentyp bei jedem Zugriff explizit angeben zu muessen.
Deshalb sollten, falls var als dword angelegt wurde, diese codes das gleiche praktische Ergebnis liefern:mov eax, var mov eax, dword ptr [var]
Zwischen diesen beiden Extremen gibt es dann noch einige Mischformen. Sinn sei mal dahingestellt...
Mit der 1. Schreibweise und dieser Verwendung von Variablen solltest du aber vorsichtig sein, denn zB. NASM liest sowas als "kopiere offset von var nach eax".
IMHO: Bei Speicherzugriffen immer eckige Klammern setzen vermeidet Verwirrungen,
-
ach, kann ich hier eigentlich auch noch mein Senf dazugeben
... schön auch mal wieder was von masm zu lesen, und weniger ist in diesem Durcheinander oft mehr, aber egal jetzt
[Senf]
man kann in diesem Themenbereich öfter mal durcheinander kommen. Die Byte und Word und bis Tbyte Pointer braucht man z.B. um einzelne Werte direkt in den Speicher zu schreiben.der Befehl mov [ebx],2 geht in der Regel nicht, genausowenig wie
mov [ebx],[ecx]man lernt, glaube ich, am besten, was vor sich geht, wenn man selbst ein kleines Progamm schreibt, das Daten aus dem Speicher liest, und an eine andere Stelle zurückschreibt.
(Ich plane ja noch immer einen kleinen interaktiven Asm- Einsteigerkurs, gerade auch, um einen hilfeichen Pfad bei diesem Durcheinander zu zeigen. Ein Rahmenkonzept habe ich jetzt, es fehlen nur noch ein paar zu klärende Dinge, etwa die Struktur der Vertiefung oder wer alles mithilft, oder welche Linux/Unixversion sich in diesem Zusammenhang für Nicht-Linuxer für die 64bit Programmierteil empfiehlt.)
(grml ist super, hat aber stets ein paar Megabugs mit an Board, bei mir z.B. gibt es bei der neusten Version beim Umschalten in den Grafikmodus einen fiesen Systemabsturz. Man braucht zwar keine Grafik bei grml, aber ist trotzdem doof.)
[/Senf]
-
Jetzt hab ichs verstanden und mit dem Debugger konnte ich die Sachen jetzt auch nachvollziehen.
Das hier hab ich mir dazu mal noch aufgeschrieben vielleicht hilft es hier ja wem anderes auch nochmal weiter.
.486 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\masm32.inc includelib \masm32\lib\masm32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib .data var dword "A",0 .code start: xor ebx , ebx mov edx , offset var ; edx = 402000 ( 402000 = Offset Adresse von der Variable: var dword "A",0 mov ebx , edx ; ebx = 402000 edx = 402000 Wert der an Adresse 402000 steht = A mov dword ptr [ebx] , "B" ; ebx verändert sicht nicht ebx ist ein Zeiger auf die Offset Adresse: 402000 ; edx ist weiterhin 402000 der Wert an der Offset Adresse 402000 hat sich nur geändert ; der neue Wert an der Offset Adresse 402000 lautet jetzt: B ;mov [ebx] , "D" ; Falsche Syntax es wurde kein Datentyp mit angeben ; Fehlermeldung von MASM dazu: error A2070: invalid instruction operands mov ebx,1 ; ebx = 1 edx = 402000 ; mov ebx,"A" ; ebx würde den Wert 41 bekommen den 41Hex = A als ASCII Zeichen ;mov dword ptr [ebx] , "C" ; Geht nich ruft hier jetzt einen Fehler hervor weil ebx auf keine Offset Adresse mehr zeigt. invoke ExitProcess , 0 end start
btw. wie soll das mit diesem ASM-Einsteigerkurs genau ablaufen?
Hört sich ja erst mal interessant an.
-
@bob-: Und, welche Adressierungsart hast Du jetzt verwendet?
-
"Indirekte Adressierung", EA ist der Inhalt eines Registers. Ganz schön verwirrend, was?
-
merker schrieb:
"Indirekte Adressierung", EA ist der Inhalt eines Registers. Ganz schön verwirrend, was?
Und dieses Register, ist das nun Basis- oder Indexregister
Und wenn wir von EA (= effektive Adresse) sprechen, welche Bedeutung hat denn nun "ptr" in der Syntax
-
Die Indireke Adressierung kennt weder Basis- noch Indexregister, sondern nur Register. EBX hier als Basis- oder Indexregister zu bezeichnen, hätte nur Bedeutung für den Programmierer. Die CPU kennt beides nicht.
"mov [ebx] , 2" in C-like-Syntax wäre i.e. "*ebx = 2". Es ist aber unklar, welcher Datentyp "ebx" sein soll. "byte ptr", "word ptr", "dword ptr" legen i.e. den Datentyp von "ebx" fest:
mov byte ptr [ebx], 2 ; -> [ebx] ist ein 'byte ptr' mov word ptr [ebx], 2 mov dword ptr [ebx], 2
Alle drei haben auch unterschiedliche Opcodebytes.
-
merker schrieb:
Die Indireke Adressierung kennt weder Basis- noch Indexregister, sondern nur Register. ...
Nennt man das betroffene Register in diesem Fall nicht Basisregister
Ach egal...
Das mit byte, word, dword ist schon klar, nur "ptr" ist unverständlich, die Begriffe Adresse und ptr passen nicht zusammen... Ist jetzt aber auch egal.
-
PTR ist ein Operator. Syntax: Typ PTR Ausdruck. Aber egal.
-
Dann ist es ein falscher Operator, der auf der Assembler-Ebene nichts zu suchen hat...
-
Ein Operator generiert keinen Code. Ein Operator teilt dem Assembler nur etwas mit. Welcher wäre denn der richtige?
Nobuo T schrieb:
Falls du mal wieder die AT&T vs. Intel diskutieren willst => bitte neuen Thread aufmachen.
-
merker schrieb:
Die Indireke Adressierung kennt weder Basis- noch Indexregister, sondern nur Register. EBX hier als Basis- oder Indexregister zu bezeichnen, hätte nur Bedeutung für den Programmierer. Die CPU kennt beides nicht.
Das stimmt irgendwie nicht. Würde ich nochmal in den Unterlagen vertiefen.
merker schrieb:
"mov [ebx] , 2" in C-like-Syntax wäre i.e. "*ebx = 2". Es ist aber unklar, welcher Datentyp "ebx" sein soll. "byte ptr", "word ptr", "dword ptr" legen i.e. den Datentyp von "ebx" fest:
mov byte ptr [ebx], 2 ; -> [ebx] ist ein 'byte ptr' mov word ptr [ebx], 2 mov dword ptr [ebx], 2
Alle drei haben auch unterschiedliche Opcodebytes.
standardmäßig ginge auch noch
mov qword ptr [bx], 2 mov tbyte ptr [bx], 2
sowas wie *ebx = 2 - meine ich - stiftet in diesem Zusammenhang hier nur Verwirrung, vor allem für jene, die es in selbst in C noch gar nicht so richtig begriffen haben. sinnvoller wäre vielleicht
int 2 int *ebx_2 ebx_2 = &2
oder
int ebx[16] ebx[7] = 2
abc.w schrieb:
Das mit byte, word, dword ist schon klar, nur "ptr" ist unverständlich, die Begriffe Adresse und ptr passen nicht zusammen... Ist jetzt aber auch egal.
Als ich diesm Begriff (z.B. mov byte ptr [bx],ff) zum ersten Mal begegnet bin, hatte ich auch Schwierigkeiten damit. Ich wusste zwar schon, wie man Speicher addressieren kann, aber diese Befehlstypen sahen beängstigend lang und seltsam aus. "ptr", der Hinweis darauf das [register] für direktes(bzw.indirektes) Schreiben in den Speicher als Pointer verwendet wird, ist wohl zum Mitlesen nützlich - aber inwiefern denn unververständlich oder gar unpassend? Es wäre vielleicht mal die Geschichte dieses Befehlstypes interessant, also die Frage warum ein mov byte [reg], var nicht auch gereicht hätte. Man könnte aber zynisch betrachtet meinen, die Verkomplizierung gewisse Dinge hat Intel Glück gebracht (der Real Mode z.B. ist schon nicht so einfach zu begreifen). Na Gottseidank haben den aktuellen 64bit Modus die Typen von Amd ausbaldowert. ;))
-
merker schrieb:
... Welcher wäre denn der richtige?
An dieser Stelle gar keiner? Die eckigen Klammern [] teilen ja genug Information mit, dass es sich um eine Adressierungsart handelt. Oder übersehe ich irgendwas
ptr steht für mich für Zeiger und unter Zeigern verstehe ich Variablen. Diese Variablen enthalten Adressen auf irgendwas, z.B. auf andere Zeiger. Register und Adressbildung in der CPU mit Hilfe von Registern haben doch nichts mit Zeigern zu tun.
Wenn man auf der Assembler-Ebene einen Zeiger nutzen möchte, muss man erstens wissen, wo sich der Zeiger im Speicher befindet, also seine effektive Adresse, zweitens muss man seinen Inhalt in eines der CPU Register laden, mit dem man Adressen bilden kann. Danach kann man auf die Adresse zugreifen, auf die der Zeiger zeigt.merker schrieb:
Nobuo T schrieb:
Falls du mal wieder die AT&T vs. Intel diskutieren willst => bitte neuen Thread aufmachen.
Das hat nichts mit der durchdachten AT&T Syntax zu tun