Re: PCI Grafikkarte Empfehlung gesucht



Ralf Hildebrandt schrieb:

Dirk Wolfgang Glomp wrote:

Was darf ich mir bei pointer vorstellen, etwa "mov [esi], register"?

esi ist hier ein 32-Bit Register, welches als Adress-Register fungiert.
Also der Inhalt von esi wird als Ziel/Quell-Adresse benutzt.

Also ist esi in der Sprechweise von C und vielen anderen Hochsprachen
ein Pointer - eine Variable, deren Wert eine Adresse ist und, welche auf
ein Datum irgendwo im RAM zeigt.

Ist der pointer jetzt ein Adress-Register, oder eine Speicherstelle im
Ram,
die einen Zeiger auf einen Speicherbereich darstellt?

Wo ein Pointer liegt, ist prinzipiell egal - im Register oder im RAM.
Nehmen wir beispielsweise eine verkettete Liste. Die baut man aus
strukturen auf, welche Strukturelemente enthält, die auf die jeweiligen
Nachbarelemente zeigen. Strukturen müssen aufgrund ihrer Größe im RAM
liegen und damit liegen auch diese Pointer im RAM.

Ja so eine Sprungtabelle habe ich auch schon in Assembler benutz.

Es existieren CPU-Architekturen, wo solch ein Pointer in ein spezielles
Adressregister geladen werden muss, damit dann über dieses
Adressregister tatsächlich auf den RAM zugegriffen werden kann.

Beim PC sind die Befehle lodsb/stosb/movsb/scasb(auch mit word/dword)
den Adressregistern si(source index) und di(destination index)
und den segment registern ds(data segment) und es(extra segment)
fest zugeordnet.
Vorweg muß man also obige register mit den richtigen Adressen laden.

movsb kopiert hierbei ein byte geladen
über ds:si und schreibt es nach es:di.
(danach wird dann si und di jeweils um eins incrementiert)

Um es zu verallgemeinern: Ein Pointer selber ist eine Variable. Der Wert
dieser Variable ist die Adresse, die auf eine andere Variable (oder
allgemein "Speicherposition") zeigt. Wo der Pointer liegt (Register oder
RAM) ist erst einmal egal - wobei natürlich Register effizienter sind.

...genau.

Beim C64er gibt es die indirekt indizierte Adressierung.
Zwei aufeinander folgende Speicherbereiche,
welche in der sogenannten Zero-Page(Adresse 0 - 0FFh) nur sein dürfen,
zeigen als 16Bit-Pointer auf einen Adresse.

D.h. der Pointer liegt während seiner Dereferenzierung selber im RAM -
ungewöhnlich, aber warum nicht...

Beim C64er ist aber nicht jede adresse in der zero-page nutzbar,
wenn man allerdings auf eine Datasette verzichtet,
ist da schon mehr Platz.
Frei war auf jeden fall die Adresse 2,
so das viele diese und logischerweise
die folgende (highbyte der adresse) nutzten.
Mit drei/vier solcher Adress-Pärchen konnte man dann schon
mehrere Tabellen/Bildbereiche bewegen.

b[2] += *ap; -- exakt die Assembler-Instruktion

ap ist ein Pointer. *ap ist der Wert, auf den ap zeigt. =
Dereferenzierung des Pointers.

So richtig erkenne ich den Sinn nicht.
Eine Variable ist es doch nicht, oder?

Der Pointer ist selber eine Variable - deren Wert eine Adresse ist. Er
zeigt auf eine Adresse im RAM (also wird an dieser Adresse eine Variable
liegen).

Aha wird ja so verwirrend aufgebaut.

Warum man unbedingt das Sternchen als Dereferenzierungoperator in C
verwendet hat, ist mir natürlich unklar, denn das stiftet Verwirrung mit
der Multiplikation. Beispiel:

Dereferenzen wofür braucht man sowas?

Immer, wenn ich auf ein Datum im RAM zugreifen will, brauche ich die
Adresse, wo das Datum im RAM liegt.

Macht das der Compiler nicht alleine,
und kann man die variable sonst nicht ansprechen?

Liegt das Datum an einer (dem
Compiler) bekannten festen Adresse, wird vom Compiler der entsprechende
Adresswert eingesetzt.
Will ich aber selber auf irgendwelche Variablen im RAM (Stack, Heap)
zugreifen und sind diese Variablen "dynamisch" (d.h. sie werden
irgendwann erzeugt und irgendwann "weggeworfen"), so muss ich einen
Pointer auf die Variablen besitzen.

Also ohne pointer keine dynamische Variable.

Einfaches Beispiel: Ich habe einen Vektor aus 10 mal 16 Bit Werten:

int vec[10];

Ich kann als eine Alternative des Zugriffes auf die Elemente des Vektors
einen Pointer nutzen:

int *pointer;

Ich hole mir die Adresse des ersten Vektorelementes mit &vec[0] und
weise diesen Wert dem Pointer zu:

pointer = &vec[0];

Also in *pointer ist die Adresse von vec[0]
und man kann über diese Adresse den Inhalt von vec[0] auslesen.


Will ich nun jedes zweite Vektorelement mit einem Wert vergleichen,
schreibe ich:


mov cx, 0 ; counter

for ( i=0; i<10; i+=2 ) { // von 0 bis 9, jeweils um 2 incrementieren
if (*pointer == vergleichswert) { //Dereferenzierung

Ja hier wird *pointer wie ein base-Register benutzt.

P1: cmp [si], vergleichswert

//aktion
}
pointer+=2;

add si, 2

add cx, 2
cmp cx, 10 ; compare
jb P1 ; jump below

}

Wie gesagt muss ich nicht extra einen Pointer für den Vektorzugriff
nutzen, aber das Beispiel ist nicht allzu kompliziert, sodass ich das so
gewählt habe. Es soll eines zeigen: Ich modifiziere den Zeiger pointer
ständig, um auf das richtige Element zu zeigen und wenn ich darauf
zeige, nutze ich den aktuellen Adresswert dieses Pointers.

Ich glaube soweit habe ich es begriffen.

c<=a**b; // beschissen formatiert
c<=a * *b; // einigermaßen lesbar


Oha.

(Multipliziere a mit dem Wert, auf den b zeigt und schreibe das Ergebnis
auf c.)


Warum ist in b nicht gleich der Wert drin?


Diese Frage ist ein "Optimierungsproblem". Wenn aus irgendwelchen
Gründen der Wert, auf den b zeigt unbedingt im RAM liegen muss, brauche
ich einen Pointer auf diesen Wert. Vielleicht muss ich ja auch erst
einmal den Wert, auf den b zeigt, finden? Wenn ich z.B. aus einem Vektor
irgendwann mal das größte Element herausgesucht habe, kann ich in b die
Adresse des größten Elements abspeichern. Und wenn ich das größte
Element haben möchte, Dereferenziere ich den Pointer b - ich hole mir
den Wert, auf den b zeigt.

Erinnert mich irgendwie an ein array in Basic, welches man mit
DIM a(2,2,2,2,) anlegt, nur gibt es da keinen speziellen pointer,
mit nimmt halt nur eine Variable als Zähler.

Aber nein, auch für nur ein movq(MMX-Befehl) gibt es ja schon viele
Adress-Kombinationen, das ein Makro erstellen, doch etwas Zeit
in Anspruch nimmt. Wäre dann ja schon zum Achtel ein Assembler.

Ich kann mir vorstellen, dass das Zusammenschieben der einzelnen Bits,
um daraus einen gültigen Opcode zu erstellen, extrem kompliziert ist.

Nö. Weiß man erstmal wie man die (3/4 gerade nicht zur Hand)Tabellen
der Intel-Doku zu lesen hat, geht es zügig.

DB 67h, 0Fh, 6Fh, 6 ; movq mm0, [esi]

67 0F = leitet mmx ein
6F = movq mmx,mem ; mmx-opcode des Befehls
6 = mm0 mit esi
Hier im letzten Byte wird ggf....
sib und scale etwa [esi + edx * 4 + value(8/32Bit)]
....benutzt.

esi = base-adress pointer
edx = index-adress pointer

Falls man das aber hinbekommt, kann man mit so einem Makro dann wieder
so programmieren, als würde dieser Opcode voll unterstützt werden.

Klar.

Auch ist VMWare leider nicht kostenlos.

Doch - kostenlos seit kurzem bis auf die high-end Server-Version.

Oh das ist mir neu. Das brauch ich dann doch.
Wie groß ist denn das so und hast du einen link zur Hand?

Dazu kann ich dir wirklich nichts sagen und muss dich auf die
Suchmaschinen und die Webseite von VMWare verweisen. Ich hatte nur die
Info aus der c't und dem Heise-Newsticker. Ich selber benötige nicht
wirklich eine virtuelle Maschine.

Gut dann werf ich morgen mal ne Suche an.

Dirk
.



Relevant Pages


Loading