Frage zu Register
-
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
-
Kann bitte jemand die Essenz dieses eher verwirrenden Threads zusammen fassen?
-
nachtfeuer schrieb:
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.
In den Unterlagen steht "wirkt wie" und nicht "ist" ein Basisregister. Soll jetzt keine Haarspalterei sein.
nachtfeuer schrieb:
standardmäßig ginge auch noch
mov qword ptr [bx], 2 mov tbyte ptr [bx], 2
Es gibt bei MOV keine Variante, die das ermöglichen könnte. Falls das vom Assembler keine Fehlermeldung gibt, dann hat er wahrscheinlich mehrere Befehle hintereinander generiert, um es umzusetzen.
nachtfeuer schrieb:
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.
Ja gut, meine "C-like-Syntax" sollte auch nur Pseudocode sein und eher wie eine Gleichung gelesen werden.
abc.w schrieb:
An dieser Stelle gar keiner? Die eckigen Klammern [] teilen ja genug Information mit, dass es sich um eine Adressierungsart handelt. Oder übersehe ich irgendwas
Streng genommen teilen die eckigen Klammern nur mit, daß es sich bei dem Ausdruck um eine Speicherreferenz handelt. Zwischen den eckigen Klammern steht dann die Art und Weise, wie die EA ausgerechnet werden soll. Davon gibt es ja diverse Varianten.
Aber es fehlt noch eine eindeutige Größenangabe, was heißt, wieviel Bytes (oder Bits) da hin geschoben werden sollen. ATT macht das klar via Suffix movb, movw, movl, popl
,pushl
. Intel eben via Operator PTR.
abc.w schrieb:
... durchdachten AT&T Syntax ...
Bei Dir heißt ja "durchdachte Syntax" lediglich, daß der Assembler von sich aus keine Optimierungen vornehmen soll/kann/darf.
-
abc.w schrieb:
ptr steht für mich für Zeiger und unter Zeigern verstehe ich Variablen.
Das mag wohl das größte Problem mit PTR sein. Praktisch selbst verursacht. In keiner Unterlage steht, daß PTR die Abkürzung für POINTER sein soll. Beispiel:
Turbo Assembler Quick Reference Guide schrieb:
BYTE
(syntax:) BYTE expression
Forces address expression to be byte size.BYTE PTR
(syntax:) BYTE PTR expression
Forces address expression to be byte sizePTR
(syntax:) type PTR expression
Forces address expression to have type sizeKein Wort von Zeiger.
-
merker schrieb:
abc.w schrieb:
... durchdachten AT&T Syntax ...
Bei Dir heißt ja "durchdachte Syntax" lediglich, daß der Assembler von sich aus keine Optimierungen vornehmen soll/kann/darf.
Nein, durchdacht heißt für mich einfach durchdacht und ich bestreite auch, dass die sogenannten "Optimierungen", die vom Assembler durchgeführt werden, wirklich als Optimierungen zu bezeichnen sind. Das, was man unter "Optimierung" versteht, ist einfach auf die Limitierung der Syntax des verwendeten Assemblers zurückzuführen. Die Entwickler haben gesehen, die Syntax erlaubt keine eineindeutige Unterscheidung, also wird der Befehl irgendwie übersetzt, damit es passt.
Die Limitierung der Syntax ergibt sich, weil entweder die Syntax zu kompliziert wird, weil alles zu unterstützen wäre zu komplex, oder weil man sich von vornherein auf das eine oder andere Feature verzichtet.
Soweit ich weiss, unterstützt der MASM Assembler (vielleicht TASM auch nicht) keine direkte Adressierungsart mit bekannten Displacements (bitte korrigiert mich, wenn meine Aussage falsch ist, aber es gab hier im Forum mal einen Thread, wo es nicht ging), d.h. so was geht nicht:
movl $42, 1000
Weil man sich darauf bewusst oder unbewusst verzichtet hatte, gibt es keinen Bedarf, in der Syntax zwischen Konstanten und Displacements zu unterscheiden. Also kein Bedarf, ein $-Zeichen einzuführen (oder ein anderes Zeichen). Nun hat sich in der Syntax eine Lücke ergeben, die man mit einem "mov , OFFSET" gestopft hatte. Damit hat man noch eine Verzerrung der Begriffe Offset und Displacement eingebaut: Offset ist nun ein Begriff für Displacement. Das ist für mich nicht durchdacht. Wenn durchdacht, dann:
movl variable, %eax # Lade den Inhalt der Variable in eax movl $variable, %eax # Lade das Displacement der Variable als Konstante in eax movl 1000, %eax # Lade den Inhalt der Speicherzelle mit der Adresse 1000 in eax movl $1000, %eax # Lade die Konstante 1000 in eax
Also alles durchdacht einheitlich...
merker schrieb:
abc.w schrieb:
ptr steht für mich für Zeiger und unter Zeigern verstehe ich Variablen.
Das mag wohl das größte Problem mit PTR sein. Praktisch selbst verursacht. In keiner Unterlage steht, daß PTR die Abkürzung für POINTER sein soll.
Toll, wofür steht es denn
Eine weitere Verzerrung der Begriffe
-
abc.w schrieb:
Wenn durchdacht, dann:
movl variable, %eax # Lade den Inhalt der Variable in eax movl $variable, %eax # Lade das Displacement der Variable als Konstante in eax movl 1000, %eax # Lade den Inhalt der Speicherzelle mit der Adresse 1000 in eax movl $1000, %eax # Lade die Konstante 1000 in eax
Also alles durchdacht einheitlich...
Kannst Du mal für diese vier Befehle die generierten Opcodebytes posten?
abc.w schrieb:
Nein, durchdacht heißt für mich einfach durchdacht und ich bestreite auch, dass die sogenannten "Optimierungen", die vom Assembler durchgeführt werden, wirklich als Optimierungen zu bezeichnen sind.
Konsequenterweise dürfte dann der Assembler nicht selbstständig festlegen, ob bei einem Sprungziel auch ein "kurzer" (also +/- 126 Bytes) reichen würde.
abc.w schrieb:
Toll, wofür steht es denn
PTR steht für PTR. Das soll jetzt wirklich kein Witz sein.
-
merker schrieb:
Kannst Du mal für diese vier Befehle die generierten Opcodebytes posten?
Ja, gerne. Die Datei tmp.s:
.global _start .section .data variable: .long 0x12345678 .section .text _start: movl variable, %eax movl $variable, %eax movl 1000, %eax movl $1000, %eax ret
Gebaut mit:
as tmp.s -o tmp.o ld tmp.o -o tmp_exe
Ausgabe von objdump:
tmp_exe: file format elf32-i386 Disassembly of section .text: 08048094 <_start>: 8048094: a1 ac 90 04 08 mov 0x80490ac,%eax 8048099: b8 ac 90 04 08 mov $0x80490ac,%eax 804809e: a1 e8 03 00 00 mov 0x3e8,%eax 80480a3: b8 e8 03 00 00 mov $0x3e8,%eax 80480a8: c3 ret
-
merker schrieb:
abc.w schrieb:
Toll, wofür steht es denn
PTR steht für PTR. Das soll jetzt wirklich kein Witz sein.
Na gut... dann ist es wohl so
-
Dein Assembler hat optimiert.
Bei "movl variable, %eax" hat er die "A1-Variante" von MOV genommen, die nur mit EAX funktioniert, aber nicht mit den anderen Registern.
Könntest Du mal "Displacement" im Zusammenhang mit (globalen) Variablen näher erläutern?
-
merker schrieb:
Dein Assembler hat optimiert.
Bei "movl variable, %eax" hat er die "A1-Variante" von MOV genommen, die nur mit EAX funktioniert, aber nicht mit den anderen Registern.
Stimmt... aber das fällt in die Kategorie "die Syntax wird zu kompliziert, weil alles zu unterstützen wäre zu komplex" und nicht, weil "man auf ein Feature verzichtet".
merker schrieb:
Könntest Du mal "Displacement" im Zusammenhang mit (globalen) Variablen näher erläutern?
Was meinst Du genau? Die Variablen werden ähnlich wie Sprungmarken deklariert und bekommen nach dem Linken eine eindeutige Adresse. Greift man auf diese Adresse zu, wird diese übersetzt in das, was man bei den Adressierungsarten (laut Intel-Konvention
) als Displacement bezeichnet... so verstehe ich das...
-
Erhard Henkes schrieb:
Kann bitte jemand die Essenz dieses eher verwirrenden Threads zusammen fassen?
Es geht um eckige Klammern Erhard...
Falls du wirklich verwirrt bist, dann kannst du dich freuen, denn der kleine interaktive Asm-Einführungskurs, den ich plane, ist bald fertig.