;************************************** ;* lineare Steigungsfunktion berechnen* ;* und grafisch darstellen. * ;* 2010 H.V.Viehof * ;************************************** ;---------------------------------------------------------- ; SetGraph Macro - Graphikmodus setzen ;---------------------------------------------------------- SetGraph MACRO ; al = Modus mov ah, 0 ; die Funktion 0 des Videointerupts int 010 #EM ;---------------------------------------------------------- ; ClearScreen Macro ; ;---------------------------------------------------------- ClearScrn MACRO ; loescht den Inhalt des Videorams mov bx, 0 mov ax, 0a000 ; Segmentaddresse des Videoram mov ds, ax ; setzen ClearLoop: mov ds: b[bx], 0 ; 0 an die Addresse speichern inc bx ; bx hochzaehlen fuer naechsten Punkt cmp bx, 38400 ; das sind 80x480 Bytes mit je 8 Bildpunkten jnz ClearLoop ; tekrarla! #EM ;---------------------------------------------------------- ; DrawPixelD Macro - einzelnen Punkt zeichnen durch unmittelbaren ; Zugriff auf den Grafikspeicher bei a000:0000 ;---------------------------------------------------------- DrawPixelD MACRO ; einzelne Punkte unmittelbar ins Videoram push es ; Register sichern push dx push cx xor ah, ah ; soll 0 sein wegen der Schiebeoperation mov al, 10000000xb ; ein Bit links setzen für einen Punkt and cx, 7 ; die unteren drei Bits von CX addressieren das Bit shr ax, cl ; das Bit fuer den Punkt auf Position schieben pop cx ; alten Wert von CX zurueckholen push cx ; und auch wieder auf den Stack push ax ; AL von AX zeigt auf das einzelne Bit shr cx, 3 ; CX / 8 denn drei Bits ergaben ja die Punktposition mov bx, 80 ; 80 Bytes ist die Zeile lang mov ax, dx ; DX (Spaltenposition) in AX mov dx, 0 ; DX loeschen denn es wird multipliziert mul bx ; Speicheraddresse = Zeile + Spalte x 80 add ax, cx ; deshalb: addieren mov bx, ax ; In BX, das wird als Pointer benutzt mov dx, 0a000 ; Segmentaddresse des Videoram mov es, dx ; setzen pop ax ; im 'alten' AL befindet sich die Bitposition or al, es: b[bx] ; diesen neuen Punkt per Oder in das Speicherbyte einfuegen mov es: b[bx], al ; an dieselbe Addresse zurueckspeichern pop cx ; 'alte' Register wiederherstellen pop dx pop es #EM ;---------------------------------------------------------- ; DrawLine Macro - horizontale Linie ; dx = position y / hoehe ;---------------------------------------------------------- DrawLineD MACRO mov cx, 0 push es mov ax, 0a000 ; Segmentaddresse des Videoram mov es, ax ; setzen LineLoop: push dx ; Register sichern push cx shr cx, 3 ; CX / 8 denn drei Bits ergaben ja die Punktposition mov bx, 80 ; 80 Bytes ist die Zeile lang mov ax, dx ; DX (Spaltenposition) in AX mov dx, 0 ; DX loeschen denn es wird multipliziert mul bx ; Speicheraddresse = Zeile + Spalte x 80 add ax, cx ; deshalb: addieren mov bx, ax ; In BX, das wird als Pointer benutzt mov es: b[bx], 0ff ; 0ff an die Addresse speichern pop cx ; 'alte' Register wiederherstellen pop dx inc cx ; cx hochzaehlen fuer naechsten Punkt cmp cx, 027f ; zeichne eine Linie, die 0x280 Spalten lang ist jl LineLoop ; den naechsten Punkt zeichnen pop es #EM ;---------------------------------------------------------- ; DrawVLine Macro - zeichnet vertikale Linie ; cx = position x ;---------------------------------------------------------- DrawVLineD MACRO ; dieses Macro ist etwas anders mov dx, 0 ; DX zaehlt PunktPositionen in einer Reihe von oben nach unten vLoop: DrawPixelD inc dx cmp dx, 01e0 ; zeichne eine vertikale Linie bis dx = 480 unterer Bildschirmrand jl vLoop #EM ;______________________________________ ; ; stapelsegment : ;______________________________________ stack segment stack word 'stack' dw 90 dup (?) stack ends CODE SEGMENT WORD PUBLIC 'CODE' ASSUME CS:CODE, DS:data, SS:stack, ES:variablen start: mov ax, seg variablen ; Vorbereiten von mov es, ax ; Datensegment und mov es: b FensterPos, 2 ; x Position des Textfensters mov es: b color, 25 ; Farbe des Textes mov es: w Step, 40 ; Maschenweite des Gitters mov es: b Merker, 2 ; Text anzeigen / verbergen mov es: w teiler, 640 mov es: w multipl, 20 mov es: w zuschlag, -80 ;---------------------------------------------------------- ; In Videomodus 640 * 480 mit 16 Farben wechseln ;---------------------------------------------------------- mov al, 012 ; 012h ist genau der richtige Modus SetGraph ; 06a wäre 800 x 600 evtl. 18 = 1024 x 768 moegl. drawall: ClearScrn ; Bildschirm 'schwarz malen' ;---------------------------------------------------------- ; Raster zeichnen ;---------------------------------------------------------- mov dx, 480 ; Startwert fuer die erste hor. Linie X1: DrawLineD ; Das Macro oben sub dx, es: w Step ; DX + Step = Position der naechsten hor. Linie cmp dx, 0 ; oben angekommen? jg X1 ; noch nicht? dann: weitere Linie mov cx, 0 ; Startwert fuer die erste ver. Linie X2: DrawVLineD ; im Prinzip dasselbe wie fuer die horz. Linien... add cx, es: w Step ; wieder: alte Linie + Step = neue Linie cmp cx, 0280 ; bis Pos. 640 jle X2 ; erreicht ;---------------------------------------------------------- ; Funktionsgraph zeichnen ;---------------------------------------------------------- mov ax, seg data ; dort sind Konstanten mov ds, ax mov ax, seg variablen ; und da Variablen mov es, ax fninit ; Coprozessor initialisieren R1: mov es: w ein, 5120 ; entra: mov cx, es: w ein ; cx = x Wert shr cx, 3 fild es: w ein ; Wert aus Speicherstelle laden fidiv es: w teiler ; durch Korrekturwert teilen fimul es: w multipl ; multiplizieren fiadd es: w zuschlag ; frndint ; auf ganze Zahl runden fistp es: w aus ; ST0 in den Speicher schreiben mov dx, 240 ; 240 ist die Bildschirmitte von oben sub dx, es: w aus ; davon subtrahiere ich die Ausgabe der Funkt. DrawPixelD ; das Macro zeichnet den Punkt an cx/dx dec es: w ein jz TextOut jmp entra ; solange Wert > 0 das oben alles wiederholen ;---------------------------------------------------------- ; Textdarstellung ;---------------------------------------------------------- TextOut: test es: b Merker, 1 ; Merker != 0: Fenster anzeigen jnz >L4 ; Merker == 0: Fenster verbergen mov si, offset message ; Anfang des Textes mov dh, -1 ; Positionen laden: Anfang Textfensteroberkante mov bl, es: b color call OutText L4: test es: b Merker, 2 ; Merker != 0: Fenster anzeigen jnz Key ; Merker == 0: Fenster verbergen mov si, offset formel ; Anfang des Textes mov dh, 7 mov bl, es: b color call OutText ;---------------------------------------------------------- ; Auf Eingabe eines Zeichens warten ;---------------------------------------------------------- Key: mov ah, 7 ; auf Tastendruck warten int 021 ; ein 'Minimenu' cmp al, 'b' ; dieses und alle unten: Vergleiche Eingabe mit zugeordnetem Zeichen jnz W1 ; immer: springe zu naechstem Vergleich wenn ungleich dec es: w zuschlag ; tue genau das wenn Eingabe korrekt identifiziert jmp drawall ; und Ruecksprung W1: cmp al, 'B' jnz W2 inc es: w zuschlag jmp drawall W2: cmp al, 'c' jnz W3 dec es: b color jmp drawall W3: cmp al, 'C' jnz W4 inc es: b color jmp drawall W4: cmp al, 'm' jnz W5 dec es: w multipl jmp drawall W5: cmp al, 'M' jnz W6 inc es: w multipl jmp drawall W6: cmp al, 'f' jnz W7 xor es: w Merker, 2 ; das XOR realisiert einen 'Toggleswitch', cok güzel! jmp drawall W7: cmp al, 'h' jnz W8 xor es: w Merker, 1 jmp drawall W8: cmp al, 'q' jnz Key ;---------------------------------------------------------- ; Videomodus zurückschalten und Programm beenden ;---------------------------------------------------------- mov al, 3 SetGraph mov ax, 04C00 int 021 ;---------------------------------------------------------- ; Textdarstellung ;---------------------------------------------------------- OutText: xor bh, bh ; geloescht, weil das die Textbildschirmseite ist mov cx, 1 ; nur einmal das Zeichen ausgeben L5: inc dh mov dl, es: b FensterPos ; Anfang der dargestellten Zeile L3: ds: lodsb ; zeichen holen cmp al, 0 ; 0 beendet die Textausgabe jz ret ; Ende Textdarstellung cmp al, 0a ; oa ist Ende der dargestellten Zeile jz L5 L1: mov ah, 2 ; cursor setzen int 010 mov ah, 9 ; Funktion 9 von Int 010: Zeichendarstellung mit Attributen int 010 inc dl jmp L3 ret CODE ENDS ;______________________________________ ; ; Datensegment I: Text, feste Faktoren ;______________________________________ data segment public word 'daten' message db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",0a db "³ Key to quit! ³",0a db "³ to show / hide Infobox ³",0a db "³ to change Messagecolor ³",0a db "³ change Function ³",0a db "³ (C) 2010 H.V.Viehof ³",0a db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",0 formel db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",0a db "³Funktionvorschrift: ³",0a db "³ m ³",0a db "³ y = x ÄÄÄ + b ³",0a db "³ n ³",0a db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",0 data ends ;______________________________________ ; ; Datensegment II: 'echte' Variablen ;______________________________________ variablen segment public word 'daten' ein dw ? aus dw ? aus2 dw ? multipl dw ? teiler dw ? zuschlag dw ? Step dw ? color db ? Merker db ? FensterPos db ? variablen ends END start