Variablenbezüge in Assembler innerhalb Pascal

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von Dosenware »

@Dirk
warum nicht einfach so?
AL hat genau 16 Möglichkeiten für die verschiedenen Blocktypen und so sparst du dir das Vergleichen.

Code: Alles auswählen

; Sprungtabellle
JUMPTAB DW OFFSET ROUTINE1, OFFSET ROUTINE2, OFFSET ROUTINE3, ...... usw.

SUCH:  and  ax,15               ; löschen der Parameter und von ah
       lea  si,[ax+ax+OFFSET JUMPTAB]
       mov  ax,[si]             ; Sprungadresse
	    call si                  ;Aufruf des Unterprogramms
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von freecrac »

Dosenware hat geschrieben:@Dirk
warum nicht einfach so?
AL hat genau 16 Möglichkeiten für die verschiedenen Blocktypen und so sparst du dir das Vergleichen.
Ja, das ist dann noch besser.

Code: Alles auswählen

       lea  si,[ax+ax+OFFSET JUMPTAB]
Ups. Kleiner Fehler. Für 16 Bit können nur bx, si, di, bp und sp in [] Klammern als Adressregister verwendet werden, aber ax, cx und dx leider nicht.

Dirk
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von Dosenware »

Dann halt so:

Code: Alles auswählen

; Sprungtabellle
JUMPTAB DW OFFSET ROUTINE1, OFFSET ROUTINE2, OFFSET ROUTINE3, ...... usw.

SUCH:  mov  bx,ax
       and  bx,15               ; reduzieren von BX auf eine Tetrade
       lea  si,[bx+bx+OFFSET JUMPTAB]
 	   call si                  ;Aufruf des Unterprogramms, [] nötig?
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von freecrac »

Dosenware hat geschrieben:Dann halt so:

Code: Alles auswählen

; Sprungtabellle
JUMPTAB DW OFFSET ROUTINE1, OFFSET ROUTINE2, OFFSET ROUTINE3, ...... usw.

SUCH:  mov  bx,ax
       and  bx,15               ; reduzieren von BX auf eine Tetrade
       lea  si,[bx+bx+OFFSET JUMPTAB]
 	   call si                  ;Aufruf des Unterprogramms, [] nötig?
Ja genau so ist es erlaubt.

Dirk
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von DOSferatu »

Genau. Selbst in Hochsprachen sollte man sich - zumindest, wenn es schnell gehen soll oder sehr viele Entscheidungen zu treffen sind, von if- oder case- Kaskaden verabschieden. Ich benutze das zwar auch noch, aber nur in unkritischen Bereichen oder wo es nicht so wichtig ist.
Ansonsten sind Entscheidungstabellen dem einfach vorzuziehen.
Und in Assembler sowieso: Immer Sprungtabellen oder Wertetabellen und diese indiziert auslesen oder indiziert springen.
Anders wäre es mir gar nicht möglich gewesen, den Geschwindigkeitszuwachs, den man durch Assemblerprogrammierung gewinnt, richtig auszunutzen.
Man sollte Assembler nicht wie "Hochsprache, nur mit anderen Befehlen" programmieren - sondern man sollte die Besonderheiten, die Assemblerprogrammierung bietet, entsprechend ausnutzen.

(Gar nicht auszudenken, wenn mein GameSys2 statt Entscheidungstabellen/Sprungtabellen mit kaskadierten, verschachtelten Abfragen arbeiten würde... Das wäre der reine Wahnwitz...)
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von zatzen »

Hier mein erster Versuch mit einer Sprungtabelle. Und es funktioniert... NICHT...

Code: Alles auswählen

      asm
        jmp @suchen
        @sprungtabelle:
        dw 0                             { 0 }
        dw offset decode_bitstream_asm_1 { 1 }
        dw offset decode_bitstream_asm_2 { 2 }
        dw offset decode_bitstream_asm_3 { 3 }
        dw offset decode_bitstream_asm_4 { 4 }
        dw offset decode_bitstream_asm_5 { 5 }
        dw 0                             { 6 }
        dw 0                             { 7 }
        dw 0                             { 8 }
        dw offset decode_bitstream_asm_1_transp  {  9 }
        dw offset decode_bitstream_asm_2_transp  { 10 }
        dw offset decode_bitstream_asm_3_transp  { 11 }
        dw offset decode_bitstream_asm_4_transp  { 12 }
        dw offset decode_bitstream_asm_5_transp  { 13 }

        @suchen:
        mov al, blocktype { 1 oder 2 ( 2 = transparent) }
        dec al { jetzt 0 oder 1 }
        shl al, 3 { jetzt 0 oder 8 }
        mov bl, bits { 1-5 }
        add bl, al { 1-5 oder 9-13 }
        xor bh, bh
        shl bx, 1
        lea si, [bx+offset @sprungtabelle]
        call si

      end;
Sorry falls ich da grundsätzlich noch was nicht kapiert habe...
Hier ist DOSBox sehr praktisch... Ich hätte wohl allein schon
15 Minuten mit neu booten zugebracht...

Liegt es vielleicht daran, dass es keine eigene Routine ist sondern
als erster Versuch einfach mitten in einer Pascal-Routine steht?
Hmm, hab's mal probiert, das alleine scheint's nicht zu sein.
Wäre praktisch wenn man umfangreicheren ASM Code auch einfach
mitten in Pascal Code reinbringen könnte.

...oder ist hier ein FAR-Call notwendig, und man braucht statt nur einem
Offset jeweils einen ganzen Pointer?
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von Dosenware »

nur zur Sicherheit:
mach mal:

Code: Alles auswählen

        mov al, blocktype { 1 oder 2 ( 2 = transparent) }
        dec al { jetzt 0 oder 1 }
{###}   and al,1
        shl al, 3 { jetzt 0 oder 8 }
        mov bl, bits { 1-5 }
        add bl, al { 1-5 oder 9-13 }
{###}   cmp al, 13
{###}   jg Dummyunterprogramm
und lege mal auf das dw 0 den Zeiger eines Dummyunterprogramms

halt der übliche debuggingkram...

EDIT: Moment: bits {1-5} meint den dezimalwert 1-5?
dann halt statt dem "and bl,$1F" ein Vergleich obs <=5 ist

Edit 2: oder man lässts gleich ganz raus - wird ja vom cmp eh abgefangen.
- cmp bl,13 korrigiert zu cmp al,13
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von zatzen »

Vielen Dank schonmal für die Antwort!
Leider funktioniert es immer noch nicht.
Sieht jetzt so aus:

Code: Alles auswählen

procedure dummy;
begin
end;


procedure decode_bitstream; assembler;
asm
        jmp @suchen
        @sprungtabelle:
        dw offset dummy                  { 0 }
        dw offset decode_bitstream_asm_1 { 1 }
        dw offset decode_bitstream_asm_2 { 2 }
        dw offset decode_bitstream_asm_3 { 3 }
        dw offset decode_bitstream_asm_4 { 4 }
        dw offset decode_bitstream_asm_5 { 5 }
        dw offset dummy                  { 6 }
        dw offset dummy                  { 7 }
        dw offset dummy                  { 8 }
        dw offset decode_bitstream_asm_1_transp  {  9 }
        dw offset decode_bitstream_asm_2_transp  { 10 }
        dw offset decode_bitstream_asm_3_transp  { 11 }
        dw offset decode_bitstream_asm_4_transp  { 12 }
        dw offset decode_bitstream_asm_5_transp  { 13 }

        @suchen:
        mov al, blocktype { 1 oder 2 ( 2 = transparent) }
        dec al { jetzt 0 oder 1 }
{###}and al, 1
        shl al, 3 { jetzt 0 oder 8 }
        mov bl, bits { 1-5 }
{###}and bl, 01fh
        add bl, al { 1-5 oder 9-13 }
{###}cmp bl, 13
{###}jg @dummy
        xor bh, bh
        shl bx, 1
        lea si, [bx+offset @sprungtabelle]
        call si
        @dummy:

end;
Einen Sprung in eine Procedure wollte ich nicht machen, daher nur Sprung zu label wenn größer 13...
Ich glaube aber auch nicht, dass das Problem bei den Variablen "blocktype" und "bits" zu suchen ist.
Die sind schon verlässlich in ihren Bereichen, sonst würde das bisherige Programm auch nicht
funktionieren.

Ich glaube da stimmt eher noch etwas nicht mit den Adressen.
SI muss doch den Offset enthalten, der tatsächlich in IP geladen wird, oder?
Was macht LEA... LEA erwartet eine Variable. Diese wäre hier [bx+offset @sprungtabelle]
und somit ein Eintrag aus der Tabelle. Wenn ich soweit schonmal richtig liege.
Somit hätten wir aber in SI nicht den Offset zu einer Procedure, sondern lediglich
den Offset zur Position in der Sprungtabelle...
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von Dosenware »

siehe meine Edits: cmp bl muss zu cmp al werden
Somit hätten wir aber in SI nicht den Offset zu einer Procedure, sondern lediglich
den Offset zur Position in der Sprungtabelle...
ganz ehrlich: k.a. - ist zu lang her
den Wert in si kannst du doch mal ausgeben, dann bekommst du heraus ob du die Adresse falsch ermittelst - und dann einfach mal herumprobieren...
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von zatzen »

Es ist so wie ich vermutet habe. Habe eben ein kleines
Programm zum testen geschrieben.
LEA ermittelt in diesem Fall nur die Offsets der Sprungtabelle
und nicht deren Inhalt. So, aber da ich das nun weiss müsste ja
der Schritt zur Lösung nicht mehr weit sein.

- Ok, ich hab's.
LEA SI, [BX+OFFSET @Sprungtabelle] und danach noch
MOV AX, CS:[SI]
und
CALL AX

Wundert mich ja fast dass man CS einfach so benutzen darf.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von DOSferatu »

zatzen hat geschrieben:Wundert mich ja fast dass man CS einfach so benutzen darf.
Na klar darf man CS benutzen - wieso nicht?
Außerdem benutzt man es hier ja nur LESEND. Und LESEND darf man ja ALLES benutzen.
Vom Auslesen von Speicheradressen gehen diese ja nicht "kaputt".

(Wichtig: Das gilt nicht immer für PORTs. D.h. wenn man Ports ausliest, setzt man diese damit manchmal
automatisch zurück oder auf einen anderen Wert. Ist bei PC recht eindeutig gelöst, kann man nicht verwechseln,
weil Ports ja mit IN gelesen und mit OUT geschrieben werden - nicht mit MOV. Auf manchen Systemen (z.B. C64)
wo die Ports quasi "gleichgeschaltet" mit Speicher sind, um den einfacheren Zugriff zu ermöglichen, also
Portzugriffe wie Speicherzugriffe programmiert werden, muß man da mehr drauf achten.)

Man darf auch schreibend auf Adressen, die im Segment ab CS liegen zugreifen - nur sollte man hier natürlich
wissen, was man tut. Aber dazu wurden ja schließlich Labels erschaffen...
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von zatzen »

Was ich heute auch herausgefunden habe: Man kann eine Sprungtabelle als procedure definieren und spart
sich somit den Sprung darüber, abgesehen davon dass diese dann schön abseits vom Code abgelegt ist.
Pascal macht also bei einer reinen assembler procedure zumindest kein einziges Byte davor.

Gibt wohl noch manches zu entdecken in der Weise wie man Assembler programmiert.
Das schöne ist, dass man irgendwie sehr schnell lernt. Und mittlerweile fühle ich mich
damit schon ziemlich genauso wohl wie mit Pascal Code. Wenn nicht sogar stellenweise
wohler wegen der Register, die man benutzen kann ohne sie vorher erst zu definieren.
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von zatzen »

zatzen hat geschrieben: - Ok, ich hab's.
LEA SI, [BX+OFFSET @Sprungtabelle] und danach noch
MOV AX, CS:[SI]
und
CALL AX
Es geht noch direkter, ohne LEA:
MOV AX, CS:[BX + OFFSET Sprungtabelle]
CALL AX


LEA ist ja bekanntlich quasi das gleiche wie OFFSET, nur als Befehl.
LEA brauche ich also nur dann, wenn ich wirklich eine Adresse
in ein Register laden will und damit noch etwas vorhabe.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Variablenbezüge in Assembler innerhalb Pascal

Beitrag von DOSferatu »

zatzen hat geschrieben: LEA ist ja bekanntlich quasi das gleiche wie OFFSET, nur als Befehl.
LEA brauche ich also nur dann, wenn ich wirklich eine Adresse
in ein Register laden will und damit noch etwas vorhabe.
Ja, LEA nutzt man z.B., wenn zur Zeit des Compilierens nicht bekannt ist, an welchem Offset (zum jeweiligen Segmentstart) sich das "Objekt" befindet.
Antworten