Eigene Funktionen ohne BIOS Int's



  • Hallo,
    wie würden eigentlich die BIOS Int's funktionieren wenn man sie z.B. irgendiwe nur mit in und out schrieben würden ?

    Z.B. diese Funktion um einen String auszugeben:

    si = Text
    ausgabe: 
                    lodsb                   ; load byte at ds:si into al
                    or al,al                ; test if character is 0 (end)
                    jz ende
                    mov ah,0eh              ; put character
                    mov bx,0007             ; attribute
                    int 0x10                ; call BIOS
                    jmp ausgabe
    ende:
    ret
    


  • meinst du nicht eher lodsb und stosb??
    sofern du am ende keinen unterschied feststellen kannst ist es egal wie das ding funktioniert,es kommt drauf an was rauskommt



  • int 10h ah=0Eh : "Write Text in Teletype Mode"
    Soll heissen, dass diese Funktion sowohl in Grafikmodi, wie auch im Textmodus funktioniert... In welchem Modus wolltest du das Ding jetzt benutzen?



  • 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)*2

    Im 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 koennen 😃

    Fuer 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 PixelLoop0

    Fuer 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 TextLoop

    di 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.


Anmelden zum Antworten