Eigene Funktionen ohne BIOS Int's
-
In beiden.
-
Das sind 2 verschiedene Paar Schuhe.
Beim Grafikmodus schreibst du (meist) in eine andere map, als beim Textmodus.
Der Textpuffer liegt im VGA color Textmodus an Addresse B8000 (also Segment B800 offset 0000)
Bei jedem geraden Offset steht dort immer zuerst Char und dann Colorattribut (jeweils ein Byte).
Die Bildschirmposition berechnet sich dann so (bei 80*25 chars): (y*80+x)*2Im Grafikmodus wird das schon schwieriger. Erstmal brauchst du eine Font Table (also eine Schriftzeichen-Tabelle, die die Schriftzeichen in Form von Bitmaps enthaelt. Ein Bit=1Pixel) Falls du absolut unkreativ bist, oder dir die Erstellung zu viel Arbeit macht, kannst du dir auch die VGA-Schrift kopieren, bevor du in den Grafikmodus schaltest...
Der Grafikpuffer liegt bei A0000. Je nach Grafikmodus kann ein Byte 1Pixel mit 256 Farben (mode 13h) sein, oder 2Pixel mit 16Farben (mode 12h).
Wie du die Bitmaps nun tatsaechlich nachher auf dem Bildschirm ausgiebst, kannst du dir selbst ausknobeln.Ich wollte hier nur die technischen Grundlagen vermitteln und hoffe das ist mir gelungen
-
Ok, könntest du ein Beispiel posten ?
-
ok. Aber nicht die vorgekauten procs.
1. Hab ich keine Lust mir dafuer jetzt was auszudenken
2. Sollst du damit auch noch Spass haben koennenFuer Ausgabe im Textmodus:
mov ax,0B800h
mov es,ax
mov ax,0C21h ;0c=Farbe 21=Ascii "!"
xor di,di
stosw ;rotes Ausrufezeichen in linker oberer Bildschirmecke. (offset 0000 in Segment B800)
Es gibt keine Luecken o.ae. im Puffer, also berechnet sich die Bildschirmposition bei 2 Byte pro char so: (y*XResolution+x)*2
(XResolution=Horizontale Aufloesung in chars. Hier meist 80. Im Grafikmodus steht XResolution fuer Anzahl der horizontal angeordneten Pixel. Im Mode 13h sind das 320)Ausgabe im Grafikmodus (320*200*256):
Bitmap db 01h,02h,04h,08h,10h,20h,40h,80h ;8*8 Pixel (ein Schraegstrich);Farbe in bl
mov ax,0A000h
mov es,ax
xor di,di
mov si,offset Bitmap
mov cx,0008h
PixelLoop0:
lodsb
push cx
mov cx,0008h
PixelLoop1:
shr al,01h
jnc short SetNoPixel
mov [byte ptr es:di],bl ;Pixel mit Farbe bl setzen
SetNoPixel:
scasb ;di+1
loop PixelLoop1
pop cx
add di,312 ;eine Zeile runter (320-8)
loop PixelLoop0Fuer die Berechnung der Bildschirmposition gilt hier das gleiche, wie im Textmodus, nur dass pro Pixel nur ein Byte benoetigt wird. Daher: y*XResolution+x
Hoffe das reicht jetzt als Denkanstoss... :p
[ Dieser Beitrag wurde am 15.07.2002 um 19:44 Uhr von Nobuo T editiert. ]
-
Ja, aber irgendwie steht dann bei mir immer nur ein gelbes Notenzeichen in der Ecke.
Noch mal ne sehr dummer Frage :-):
mov ax,0C21h ;0c=Farbe 21=Ascii "!"
heißt das das ich auch die Farbe in al und das Zeichen in ah packen könnte?
-
Wenn beim Ausfuehren des ersten Codeteils statt eines roten Ausrufezeichens ein gelbes Notensymbol erscheint, hast du entweder den Code irgendwie falsch umgesetzt oder dein PC/OS ist irgendwie andersrum
Kann mir ehrlichgesagt net so ganz erklaehren, wie das zustande kommen soll... Der sourcecode wuerde mich mal interessieren.
Zur 2. Frage:
genau andersrum. al Zeichen und ah Farbe.
-
Also ich weiß nich woran es lag, aber jetzt funktioniert der Code.
Ich hab noch mal eine Frage zu Positions bestimmung. Nachdem ich das Zeichen ausgegeben habe, muss ich ja dieses rechnen "(y*80+x)*2". Aber wo hin dann mit dem Ergebniss ? Muss das dann in den ah und in den al dann wieder 0B800h ?
-
Das Ergebnis dieser Rechnung ist das Offset im Bildschirmpuffer, gehoert also zu di.
Und das Speicheroffset muss nicht nach jeder Zeichenausgabe neu berechnet werden. Wenn du zB. einen String ausgeben willst reicht so was hier:
;laenge des Strings = cx Farbe = ah Pointer zum String = ds:si
;di zeigt in den Bildschirmpuffer es=B800
TextLoop:
lodsb ;Zeichen vom String laden
stosw ;ah=Farbe al=Zeichen => in Bildschirmpuffer schreiben
loop TextLoopdi solltest du moeglichst oft vor der Textausgabe direkt setzen, also eine fixe Zahl in den Code schreiben.
zB.
mov di,00A2h ;Zeigt bei 80*?? Zeichen in die 2. Zeile zum 2. Zeichen (x=1 y=1)
-
Moment, moment ... :-).
Irgendwie bin ich mittlerweile mehr verwirrt als "geholfen".
Also wenn ich in si den Text habe den ich ausgeben will, was muss ich dann machen, aber so das X und Y mitgezählt werden.
-
*lol* dabei ist das doch eigentlich ganz furchtbar simpel :p
Einfachste Methode:
irgendwie besagte Rechnung ausfuehren "(80*y+x)*2" und das Ergabnis in di platzieren.
es = B800 setzen
ah = Farbe setzen
ds:si zeigt wie gesagt auf den Text
und dann diesen kurzen code ausfuehren:TextLoop: lodsb ;Zeichen vom String laden stosw ;ah=Farbe al=Zeichen => in Bildschirmpuffer schreiben loop TextLoop
-
Kann man die besagte REchnung irgendwie so machen ?
mov ah,[x] inc ah mov [x],ah mov al,80 mov bh,[y] add ax, [x] xor ah,ah mov al,2 mul ax mov di,ax
-
sorry, aber hae??
Falls es dir noch net aufgefallen ist: egal welchen Wert du fuer x oder y einsetzt, nach deiner Rechnung kommt hinten immer 4 raus.Und ueberhaupt: wenn du schon nur die Haelfte der Funktionen dieses Interrupts kopierst (keine Cursor verschiebung, Controll codes werden nicht beachtet) warum willst du dann trotzdem die Form dieser Interruptfunktion beibehalten und mit dieser Proc immer nur ein Zeichen ausgeben?
aber egal: hier so ungefaehr das, was deine Rechnung da vermutlich machen sollte:
xor ax,ax mov al,[y] mov di,ax shl di,06h ;y*64 shl ax,04h ;y*16 add di,ax ;(y*64)+(y*16) macht y*80 xor ax,ax mov al,[x] inc [x] add di,ax ;y*80 +x add di,di ;((y*80)+x)+((y*80)+x) => (y*80+x)*2
-
Naja ich lerne gerade erst Assembler.
-
Da du anscheinend noch ziemlich am Anfang stehst: lass dich bloss nicht von solchen gar schrecklichen Formeln abschrecken
Und nimm nach Moeglichkeit etwas Abstand davon, fuer Kleinigkeiten, wie einzelne Buchstaben ausgeben oder Pixel nach x/y setzen, eine eigene Proc zu schreiben, des bringts einfach net
-
Ja werd ich erstmal machen, aber das eigentliche Problem was ich hatte ist das die BIOS Funktion BX benutzt. Da ich aber noch Assembler lerne benutze ich immer noch C und linke die dann. Aber mein Compiler benutzt BX für seine String Operationen und dann kommt der schon mal "durcheinander". Wenn ich aber BX auf den Stack leg und nach der Ausgabe wieder zurück hole steht nur ein lustiges Zeichen mischmasch aufm Bildschirm und es piept auch.
-
Schon merkwuerdig
kannst du denn bx nicht einfach in zB. dx oder di o.ae. ablegen?
-
Ich galub ich hab das Problem gelöst. Das Probelm war whol der Turbo C Compiller. Jedenfalls geht es mit der C++ Variante besser.