Sie sind nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: GEOS-InfoBase-Forum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

21

Dienstag, 13. März 2018, 19:22

Mal ne ganz blöde Frage: SP zeigt doch auf den ersten freien Platz auf dem Stack, oder?

D.h. PUSH AX läuft intern so ab:

Quellcode

1
2
mov [SS:SP], AX
sub sp, 2


oder wird zuerst SP vermindert und dann AX geschrieben?

Rainer
Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

22

Dienstag, 13. März 2018, 21:17

In diesem Beispiel sieht man, wie man eine Adresse des lokalen Buffers in bp bringt. Ob das das gleiche macht, wie in deiner Implementation, kann ich ad-hoc nicht sagen.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    ; ds:di = element
    ; ax = size (if paraAttr)
    ; dl = TextArrayType

ECEACallback    proc    far    uses    dx
buf    local    VisTextMaxParaAttr
    .enter

    cmp    ds:[di].REH_refCount.WAAH_high, EA_FREE_ELEMENT
    jz    done

    mov    si, di   		 ;ds:si = element
    segmov    es, ss
    lea    di, buf
    mov    cx, size VisTextMaxParaAttr
    rep movsb

    push    bp
    lea    bp, buf
    cmp    dl, TAT_CHAR_ATTRS
    jnz    notCharAttr
    call    ECCheckCharAttr
    jmp    common
notCharAttr:

23

Mittwoch, 14. März 2018, 10:35

Rainer:

Ich glaube eher, dass sp auf das letzte besetzte Byte zeigt. Dann wird sp um die Anzahl der zu pushenden Bytes erniedrigt und dann erfolgt der mov-Befehl.

Falk:

Der Name einer lokalen Variablen steht doch für den Offset vom Basepointer. Und wenn buf die zuletzt auf den Stack gebrachte Variable ist, dann zeigt sp auf das erste Byte von buf. Wenn nun der Offset zu buf von bp subtrahiert wird, dann zeigt bp ebenfalls auf das erste Byte von buf. Das kann ich doch auch erreichen, indem ich sp nach bp kopiere.


Solche Diskussionen fördern das Verständnis von der Abeitsweise des Prozessors, zumindest meins :P

24

Mittwoch, 14. März 2018, 17:44

Ob es bei GEOS exakt genau so ist, kann ich ohne näher hineinzuschaun gerade nicht sagen, denke aber es ergibt, das bp nie direkt auf die lokalen vars zeigt:

https://eli.thegreenplace.net/2011/02/04…tack-is-on-x86/

ein

lea bp, lineattr

sollte zumindest das lösen.

25

Mittwoch, 14. März 2018, 20:40

Ich glaube eher, dass sp auf das letzte besetzte Byte zeigt. Dann wird sp um die Anzahl der zu pushenden Bytes erniedrigt und dann erfolgt der mov-Befehl.
Ja, du hast tatsächlich recht, ich hab das gerade in swat nachvollzogen. Mist, ich dachte echt es sei anders herum ;-)

mov bp, sp belegt also wirklich BP mit der Adresse der lokalen Variablen.

Quellcode

1
2
3
4
5
6
7
8
@method MandelProcessClass, MSG_DISP_TEST {
int v;
	v= 0x55AA;
	asm mov ax, v
	asm add ax, 0x1111
	asm push ax
	asm pop ax
}


Nach v = 0x55Aa sieht man, dass [SP] 0x55AA ist. Nach push AX ist [SP] 0x66BB.

Gruß
Rainer
»Rainer« hat folgendes Bild angehängt:
  • swat sp-test.gif
Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

26

Mittwoch, 14. März 2018, 21:20

Hi Rainer,
nach der ESP PDF-Doku Seite 68 ist das richtig, wenn man keine zusätzlichen uses hat, theoretisch.

@Wilfried, hast Du ein Beispielprojekt, das man zum selbst-Debuggen einfach mal verwenden kann?

Grüße,
Falk

27

Mittwoch, 14. März 2018, 22:20

Ich spiele mit dem Sample Dupgrobj herum.
Zeichne eine Linie (die schon vorhandene ist kein GrObj), ändere über Line Attributes Farbe und/oder Dicke, geh dann auf Linieneigenschaften. Zuerst wird das LineToken der Linie angezeigt (funktioniert) und nach ok geht es in die asm-Prozedur (Aufruf in GOC mit la(linetoken, @GCGOAM) in der Methode GCGrObjAttributeManagerClass, MSG_GOAM_GET_LINE_WIDTH).
Ich schicke dir den Ordner (jetzt).

28

Mittwoch, 14. März 2018, 22:26

Falk, ist die Mail angekommen?

29

Donnerstag, 15. März 2018, 07:15

Bisher leider nicht ;(

30

Donnerstag, 15. März 2018, 10:46

Dann schicke ich dir das Spielprojekt eben auf diese Weise:-).
Zeichne eine Linie (die vorhandene ist kein GrObj), verändere ihre Eigenschaften über Line Attributes und geh dann auf Linieneigenschaften. Zunächst wird das LineToken ausgegeben (funktioniert), danach geht es in die asm-Prozedur. Sie wird aufgerufen mit la(linetoken,@GCGOAM) in der Methode GCGrObjAttributeManagerClass, MSG_GOAM_GET_LINE_WIDTH.

Ich merke gerade:
Das Hochladen geht hier wegen Übergröße offensichtlich auch nicht:-(.
Dann fällt mir im Moment kein Weg mehr ein, wie ich dir die Datei zukommen lassen kann.

31

Donnerstag, 15. März 2018, 10:57

Ich hab den Ordner jetzt auf das Notwendigste reduziert, jetzt klappt es:-)
»Wilfried« hat folgende Datei angehängt:
  • DUPGROBJ.zip (20,35 kB - 38 mal heruntergeladen - zuletzt: Heute, 02:27)

32

Donnerstag, 15. März 2018, 17:04

Was mir gerade einfällt: hast du in swat geprüft, ob dein optr GCGOAM korrekt übergeben wird? Es kommt manchmal dazu, dass der Compiler das @-Konstrukt falsch übersetzt. Aber ich glaube, dann gibt es eine Fehlermeldung, bin aber nicht ganz sicher.
Rainer
Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

33

Donnerstag, 15. März 2018, 18:21

Wenn ich mir mit locals die Parameter und die lokale Variable ansehe, dann erscheint dort eine Zeile mit
parameter void _optr GCGOAM at [bp+6] = *GCGOAM{GCGrObjAttributeManagerClass} (@1, ^l5e60h:0020h).
Also gehe ich davon aus, dass die Übergabe korrekt ist. Die angegebene Adresse steht so auch in bx:si (mit reg kontrolliert). Was bedeutet eigentlich ^l vor der Adresse?

34

Donnerstag, 15. März 2018, 18:56

Habe die Erklärung für ^l gerade selbst gefunden:-)

35

Donnerstag, 15. März 2018, 21:45

Was ist es denn?
d[ 0_O ]b

36

Donnerstag, 15. März 2018, 23:48

^l
The carat-l is used to dereference an optr, a pointer in the form handle:chunk-handle (this is also known as a "local memory pointer"). This is similar to the ^h operator, but ^l requires a chunk handle rather than an offset. If an optr is stored in CX : DX, for example, the ^l operator could be used to dereference it as follows:
[hello3:0] 11 => pobj ^lCX : DX
[hello3:0] 12 => pobj ^l0x43d0 : 0x022

Zitat aus der Doku, nicht meine Worte. Wird wohl auch nur von Swat benutzt. Also einfach nur eine Adressenangabe?

37

Freitag, 16. März 2018, 09:55

Also einfach nur eine Adressenangabe?


Scheint so - aber nicht irgendeine, sondern eine, die auf einen OPTR (Object Pointer) zeigt. Und da sind wir wieder bei dem Kapitel, das bei meinen Programmen die meisten Abstürze verursacht: Die komische Unterteilung in ptr, optr, handles, ... und das ganze auch noch ausgelagert oder tatsächlich im Hauptspeicher... *seufz*

GEOS Programming: 1.2 Basic Data Types and Structures: Handles and Pointers

Handles and pointers are present everywhere in GEOS--they are the essential elements that make dynamic linking and efficient memory management possible.

GEOS pointers are all far pointers; that is, they are 32-bit addresses that reference specific locations in memory. They are normal C pointers and can be used as such. Two other pointer types are also used by GEOS: Object pointers (optrs) and segment pointers. Object pointers are described below; segment pointers are 16-bit addresses described in the Memory Management chapter.

Handles
Handles are 16-bit, unsigned values used for several purposes. They provide abstraction when the exact address of a data structure or other item is not known or is an inconsistent state. The kernel maintains a handle table to keep track of many of the handles in the system. Each entry in the handle table is 16 bytes that contains information about the item referenced by the handle; these 16 bytes are opaque to applications and libraries and can not be accessed or altered except by the kernel. Other handle types are managed in other tables by the kernel.

Handles are used for the following primary purposes. For a full description of how handles are used, see the Handles chapter.

Memory reference
Entries for memory handles contain pointers to memory blocks; when the blocks move, the pointers are updated. However, the handle's integrity is preserved, and applications keep track of just the handle value.
Virtual Memory reference
Entries for VM handles indirectly reference VM blocks similar to the way memory handles reference blocks of memory. VM handles may be used whether the VM block is resident in memory or not.
File and disk reference
Entries for file and disk handles contain information about the location and status of the referenced file/disk. They provide indirect access to files and disks in a manner similar to memory handles.
Data structure implementation
Certain frequently-used system data structures require a storage format that provides for quick and convenient access at all times. These data structures (for example, threads, event queues, messages, timers, and semaphores) are stored in Handle Table entries.
Optimization
The kernel will, if space permits, sometimes use Handle Table entries for optimized temporary storage. (For example, when passing parameters on the stack with messages, the kernel will occasionally use handles for storing the parameters.)
The NullHandle value (zero) is used to indicate a null handle.

There are over a dozen different types of handles that can be used by any sort of geode. These are listed in the GEOS Programming chapter. All are 16-bit unsigned integers.

Chunk Handles and Object Pointers
Objects and small data structures are stored in small memory pieces called chunks. Chunks are stored in memory blocks known as local memory heaps, and each local memory heap can contain several chunks. Each chunk is referenced by a combination of two handles: The MemHandle handle locates the local memory heap, and the ChunkHandle locates the chunk within the block. A null chunk handle value is specified by NullChunk .

Objects are referenced in the same way as chunks, but the handle and chunk handle are combined into a single structure called an Object Pointer, or optr. Each optr uniquely identifies a particular object in the system. Note that optrs are often used to reference non-object chunks and data structures. A null value is specified by NullOptr .

GEOS provides several macros, all defined in geos.h , for creating and parsing optrs.

ConstructOptr()
This macro constructs an optr from a MemHandle and a ChunkHandle.
OptrToHandle()
This macro extracts the MemHandle portion of the given optr.
OptrToChunk()
This macro extracts the chunk handle portion of a given optr.
Pointers
Pointers can be used normally as in C. All Goc-generated pointers are far pointers; that is, they are 32-bits long, composed of a 16-bit segment and a 16-bit offset.

GEOS provides macros for extracting the segment and handle portions of pointers.

PtrToSegment()
This macro returns the segment portion of the given pointer (returned as type "word").
PtrToOffset()
This macro returns the offset portion of the given pointer (returned as type "word").
GEOS automatically loads code resources when needed. However, when you call routines through pointers, you must take special measures to see to it that the routine is properly loaded into memory. This is discussed below in Using Routine Pointers in Goc .
d[ 0_O ]b

38

Freitag, 16. März 2018, 14:51

Ich versuch mal ne Kurzerklärung - in der Hoffnung, nicht Eulen nach Athen zu tragen.

1. Pointer zeigen auf eine Adresse im RAM, Format segmen:offset. Größe: dword (32 Bit). Z.B. liefert malloc() eine Pointer, und um die Adresse einer Variablen an eine Routine zu übergeben nutzt man die Syntax &varName.

2. Handels referenzieren eine Datenstruktur, die keine feste Adresse hat, also nicht über einen Pointer angesprochen werden kann. Da der verfügbare Speicher begrenzt ist werden nicht benötigte Speicherblöcke "ausgelagert". Um auf sie zugreifen zu können müssen sie "gelockt" werden. Solange sie gelockt sind kannst du dir einen pointer auf den Block besorgen und darüber dann auf die Inhalte zugreifen. Alternativ - wenn der Speicherblock ein "local Memory" block ist kannst/musst du eine optr verwenden.

3. Objekte sind als chunks in einem Speicherblock organisiert. Zum Konzept siehe Concepts Handbuch, Kapitel 16., Local Memory. Zum Zugriff auf ein Objekt muss ich seinen Speicherblock und das ChunkHandle in diesem Speicherblock kennen. Das macht man, indem man ein dword nimmt, im High-Word das Memhandle unterbringt und im Low-Word das Chunkhandle. Dieses Konstrukt heißt dann optr.
Damit können optr nicht nur Objekte sondern beliebige chunks in einem "Local Memory" block referenzieren, als auch Datenchunks, Chunks mit VisMoniker usw.
Deswegen gibt es auch Befehle die aus einem optr eine pointer machen - also die Adresse des chunks im Speicherblock liefern.

Das ^l brauchst du also, damit swat weiß, dass das dword ein optr ist und kein sonstwas. ^l steht für "deref local memory", wobei das ^wohl aus der Pascal Syntax stammen dürfte ;-)

4. Wenn eine Methode eines Objekts aufgerufen wird (z.B.MSG_VIS_DRAW), wird als erstes der Speicherblock mit dem Objekt gelockt. Dieser Methode werden standardmäßig zwei Parameter mitgegeben: oself und pself. oself ist der optr des Objekts, pself ist der Pointer auf den Chunk, also auf die Instancedaten des Objekts.

Also eigentlich ist es ganz einfach :P :P 8) :D

Gruß
Rainer
Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

39

Freitag, 16. März 2018, 16:25

Im Prinzip hab ich das gewusst. Es tut aber gut, die Zusammenhänge noch einmal so klar lesen zu können und das eigene Verständnis zum größten teil bestätigt zu bekommen. Die Sache mit oself und pself war mir nicht so klar. Statt als Parameter @GCGOAM zu übergeben, kann ich also oself übergeben. Gerade ausprobiert:-).
Besten Dank Rainer.

40

Freitag, 16. März 2018, 16:51

Eine weitere Unklarheit:
Ich habe ein GrObj gezeichnet und die Liniendicke verändert. Der GrObjAttributeManager sollte also sein lineAttrArray mit zwei Elementen angelegt haben. Seine Instanzvariable GOAMI_lineAttrArrayHandle sollte also nicht 0 sein. Wenn ich mir jetzt in Swat mit pobj *GCGOAM (unteranderem) die Instanzvariablen anzeigen lasse, dann steht dort der Wert 0h. Fast alle Instanzvariablen zeigen den Wert 0h. Mit p GOAMI_lineAttrArrayHandle wird allerdings 0000h:001bh angezeigt.

Zur Zeit ist neben Ihnen 1 Benutzer in diesem Thema unterwegs:

1 Besucher

Thema bewerten