wobo hat geschrieben:Ja, man muss für jede Subroutine eine eigene Pascal-Procedure schreiben (Du bist ja auch unter Pascal),
....
Die Subroutinen müssen vor den Routinen stehen, die die Subroutinen aufrufen.
Turbo Pascal ist für 80286, d.h. kann grundsätzlich nur 16-bit/286-instructions. "Pushad" etc. geht also grundsätzlich nicht.
Kennt Pascal die asm-Anweisung Define Byte (zb: DB 0,1,2,3,4)?
Weil dann könnte man doch auch 32 Bit-Register/Befehle von Hand coden und dort einbauen.
Parameter kommen auf den Stack und werden von der Subroutine beim Verlassen auch wieder entfernt.
Lokale Variablen werden wie unter Pascal angelegt und ebenfalls automatisch beim Verlassen der procedure vom Stack entfernt.
Alles andere, was Du auf den Stack schmeißt, mußt Du auch wieder selbst entfernen (z.B.: die pusha/popa oben).
Irgendwo habe ich mal gelesen, dass man den in Pascal integrierten Assembler als logischen Assembler bezeichnet, da man grundsätzlich keine Adressen berechnen muss. Wenn mir also einfällt, ich brauchte noch 6 Variablen, dann kann ich sie gefahrlos vor (und natürlich auch nach) der bereits angelegten lokalen Variable "Summe" anlegen, ohne dass ich am Code was ändern müßte.
Also z.B.:
Code: Alles auswählen
procedure Haupt( w1, w2 : word);
var ich, bin, so, ver, gess, lich : byte;
Summe: word;
begin
Summe := w1+w2;
asm
mov ax, Summe
pusha
push ax
call Sub02
popa
mov Summe, ax
end;
writeln( Summe );
end;
Ok, das habe ich nun verstanden.
Leider habe ich mit VESA noch nichts gemacht. Wie kommt man denn an die Bankumschaltungsroutine und welche Parameter erwartet diese?
Ab VBE 2 macht man es so wie folgt:
Zuerst rufen wir VBE-Function 00 auf. Dafür reservieren wir einen Buffer von 512 Byte.
Function 00h - Return VBE Controller Information
Input: AX = 4F00h Return VBE Controller Information
ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
VbeInfoBlock (512 Byte):
....
VideoModePtr dd ? ; VbeFarPtr to VideoModeList = VbeInfoBlock+0Eh
.....
Dann holen wir aus diesem VbeInfoBlock+0Eh den Pointer der auf die Vesa-Modeliste zeigt.
Nun holen wir darüber die erste Modenummer und rufen damit VBE-Function 01 auf, um damit zu überprüfen ob dieser Mode die gewünschte Auflösung und Anzahl der Farben hat. Für Function 01 brauchen wir einen weiteren Buffer(ModeInfoBlock) von 256 Bytes, die wir ebenfalls reservieren.
Function 01h - Return VBE Mode Information
Input: AX = 4F01h Return VBE mode information
CX = Mode number
ES:DI = Pointer to ModeInfoBlock structure
ModeInfoBlock: (256 Byte: Auflösung, Farbtiefe... )
...
WinFuncPtr dd ? ; real mode pointer to window function = Modeinfo-Buffer+0Ch
...
Haben wir unsere gewünschte Auflösung und damit unsere Modenummer gefunden, dann können wir nun den far call-Pointer zur Bankumschalktungsroutine aus ModeInfoBlock+0Ch holen und in unseren Pixelsetzer schreiben.
Wenn die Auflösung etc. des ersten Mode in der Modeliste nicht stimmt, dann müssen wir die nächste Modenummer aus der Liste holen und die Überprüfung mit Funktion 01 erneut wiederholen, bis wir die gewünschte Auflosung gefunden haben, oder bis die Modeliste mit FFFF endet und damit kein Mode mit den gewünschten Eigenschaften gefunden wurde.
Wenn wir unseren Mode gefunden haben:
Code: Alles auswählen
mov di, OFFSET ModeInfoBlock
mov eax, DWORD PTR[di+0Ch] ; Zeiger auf Bankumschaltungs-Routine holen
and eax, eax
jz FEHLER ; Funktion wird nicht unterstützt
mov DWORD PTR cs:[BANKSET], eax
Pixelsetzer:
; Berechnung der Adresse des Pixels; OFFSET nach DI; Banknummer nach DX
cmp dx, bp ; BP = alte Banknummer; DX = neue Banknummer
jz short NOBA ; wenn identisch, dann braucht nicht geschaltet werden
xor bx, bx ; VESA:Bankumschaltung (Fenster A)
mov bp, dx ; neue Banknummer retten
;--------------------------
PIXEL: DB 9Ah ; CALL FAR: BANKSET
BANKSET DD ? ; Zeiger auf Bankumschaltungs-Routine (OFFSET, SEGMENT)
;--------------------------
NOBA: mov DWORD PTR fs:[di], 15 ; Pixel setzen (FS = 0A000h)
Für 80286 müsste man statt EAX zu verwenden nur AX benutzen und dann zwei Lese- und Schreibzugriffe machen, damit Segment und Offset von der Bankumschaltungsroutine auch in unseren Code richtig eingetragen wird.
Für den far call zur Bankumschaltunfsroutine: Ausser die Funktionsnummer(in AX) die wir mit dem Direktansprung nicht mehr brauchen, sind es die selben Input-Parameter wie bei der Function 05, die wir auch für den far call zur Bankumschaltungsroutine benötigen.
Function 05h - Display Window Control
Input: AX = 4F05h VBE Display Window Control ; brauchen wir nicht beim far call
(16-bit) BH = 00h Set memory window
= 01h Get memory window
BL = Window number
= 00h Window A
= 01h Window B
DX = Window number in video memory in window
Alle diese VBE-Funktionen sollten im AX-Register 004Fh zurück geben, weil sonst ist ein Fehler augetreten.
Wenn noch etwas unklar ist, dann einfach noch einmal nachfragen. Ich erkläre es so lange, bis es jeder versteht der es verstehen möchte.
Genauere Details findet man im "vbe3.pdf" auf vesa.org (Registrieren/Anmelden erforderlich).
.... Der Programmierer muss gucken, dass der Stack groß genug ist. Pascal entfernt nur nach Verlassen einer Subroutine die übergebenen Parameter und die angelegten lokalen Variablen sowie die Rücksprungadresse.
Ok, was ich aber noch nicht weiss, wo wird die Stackgrösse angegeben?
Dirk