Punkt zeichnen (int 10, al 0Ch)
-
Bisher net, ich kanns ja mal versuchen Wenn mir noch jemand sagt, wo ich TASM bekomme... (in der FAQ hab ich nichts gesehen...Google versuch ich gleich nochmal :))
Edit: den 2.01er hab ich shcon..gibt aber sicher noch aktuellere Versionen, oder? ^^
Zusatz 2 Unter WinXP ist dessen funktionieren fragwürdig..ich krieg nur ein wneig roten Matsch am oberen Rand, der hatte ein paar probs, den vollbildmodus zu greifen Vielelicht morgen
[ Dieser Beitrag wurde am 30.05.2002 um 02:02 Uhr von TriPhoenix editiert. ]
-
Moin, Moin...
Der Fehler des Programms liegt in der Zeile mov al, 12. Der
betreffende Videomodus hat den Wert 012(hex). Das entspricht 18(dez)!Also entweder schreiben mov al,18 oder mov al,012h.
Außerdem sollte wieder in den Textmodus geschaltet werden, bevor das Programm beendet wird.
mov ah,0 mov al,03h int 010h ; Programm beenden
Ciao...
[ Dieser Beitrag wurde am 30.05.2002 um 08:38 Uhr von KalEl editiert. ]
[ Dieser Beitrag wurde am 30.05.2002 um 08:39 Uhr von KalEl editiert. ]
-
Wow, vielen Dank an alle! KaiEl hatte recht, mit 12h in al funktioniert es
Aber dazu muss ich sagen, dass es dann in meinem Buch falsch stand, dort standen nämlich nur 12 :pGrafikprogrammierung ist ja dann ziemlich einfach, echt super
Jetzt bastel ich mir mal ein paar Funktionen zum Beispiel zum Zeichnen eines Kreises. Ist es überhaupt möglich irgendwie Funktionen wie in C/C++ zu schreiben? Dachte man nimm Labels.ZeichneKreis:
; CodeAber dann kann ich ja nie Werte übergeben. Kann man sowas machen?
-
funktionen gibt es auch in Assembler!
Beispiel
;... call kreis ;... kreis PROC NEAR ;... ret kreis ENDP
-
Moinsen...
Ähm, mein Name lautet nicht KaiEl sonder KalEl.
Danke...
-
Danke, habe es jetzt versucht das Zeichnen der Linie in eine Funktion einzubetten, dazu habe ich auch in meinem Buch nachgelesen, aber jetzt stürtzt das Programm ab:
;----------------------------------------------------------
; Linie zeichnen
;----------------------------------------------------------Linie PROC NEAR
push bx
xor bx,bx
linie01:
mov ah, 0Ch
mov cx, bx ; Splate
mov dx, 10 ; Zeile
mov al, 4 ; Farbattribut
int 10h
inc bx
cmp bx, 20h ;zeichne eine Linie, die 0x20 Spalten lang ist
jl linie01
ret
Linie ENDPcall Linie ; Die Linie-Funktion aufrufen
Windows meldet: "Die NTVDM-CPU hat einen ungültigen Befehl entdenkt."
Was könnte der Fehler sein?
@KalEl: Sorry, werde es mir merken :p
-
ich sehe in der proc "push bx" aber kein "pop bx"
-
Und nochmal Moinsen...
Hier ein kleines Programm, das die Parameterübergabe an eine
Assemblerfunktion zeigen soll:.model small .stack 0200h .data .code start: push 10 ; 1. Parameter auf den Stack push 20 ; 2. Parameter auf den Stack call addiere add sp, 4 ; Stack bereinigen mov ah, 7 int 21h mov ah, 04Ch int 21h ; Hier folgen die Funktionen addiere proc near push bp ; Register bp sichern mov bp, sp ; Stackframe aufbauen push bx ; Registerinhalt retten mov ax, word ptr [bp + 4] ; 1. Parameter nach ax mov bx, word ptr [bp + 6] ; 2. Parameter nach bx add ax, bx pop bx mov sp, bp ; alten Wert von sp wiederherstellen pop bp ; alten Wert von bp zurückholen ret addiere endp end Start
Die Funktion addiert die beiden Parameter. Das Ergebnis steht in Register ax und kann so an das Hauptprogramm übergeben werden.
Wichtig ist, dass der Stack bereinigt wird, d.h. die Parameter werden quasi wieder vom Stack entfernt.
Diese Art der Parameterübergabe ist wie in C. Pascal macht das etwas anders.
Ciao...
-
Danke dir
Es lag an 2 Sachen, erstmal das pop bx und dann ging's immer noch nicht, da ich so dämlich war und die Funktion in den Code des start-Labels gepackt hatte *lol* :p
Also hier nochmal der vollständige Code, falls es jemand ausprobieren möchte oder ähnliches
CODE SEGMENT WORD 'CODE' ASSUME CS:CODE ;---------------------------------------------------------- ; DrawLine Prozedur ;---------------------------------------------------------- DrawLine PROC NEAR push bx xor bx,bx LineLoop: mov ah, 0Ch mov cx, bx ; Splate mov dx, 80 ; Zeile mov al, 4 ; rot int 10h inc bx cmp bx, 80h ; zeichne eine Linie, die 0x80 Spalten lang ist jl LineLoop pop bx ret DrawLine ENDP start: ;---------------------------------------------------------- ; In Videomodus 640 * 480 mit 16 Farben wechseln ;---------------------------------------------------------- mov ah, 0 mov al, 12h int 10h ;---------------------------------------------------------- ; Grünes 'a' ausgeben ;---------------------------------------------------------- mov ah, 9 mov bh, 0 ; Bildschirmseite 0 mov cx, 1 ; Ein Zeichen mov al, 97 ; 'a' mov bl, 2 ; grün int 10h ;---------------------------------------------------------- ; Linie zeichnen ;---------------------------------------------------------- call DrawLine ;---------------------------------------------------------- ; Auf Eingabe eines Zeichens warten ;---------------------------------------------------------- mov ah, 7 int 21h ;---------------------------------------------------------- ; Videomodus zurückschalten ;---------------------------------------------------------- mov ah, 0 mov al, 3h int 10h ;---------------------------------------------------------- ; Programm beenden ;---------------------------------------------------------- mov ah, 04Ch int 21h CODE ENDS END start
-
Habe auch mal ne Frage zu deinem Code KalEl:
mov ax, word ptr [bp + 4] ; 1. Parameter nach ax
mov bx, word ptr [bp + 6] ; 2. Parameter nach bxWas macht man denn, wenn man ganz viele Parameter hat? Soviele Register stehen ja garnicht zur Verfügung
-
Dann verarbeitet man die Parameter halt hintereinander. Die bleiben schliesslich auf dem Stack erhalten.
Die Parameteruebergabe via Stack erscheint mir ehrlichgesagt sowieso nur sinnvoll, wenn entweder mehr Parameter verarbeitet werden muessen, als Register zur Verfuegung stehen (kommt fast nie vor)
Der code so unglaublich kompliziert und lang ist, dass man zwischendurch die Parameter so und so pushen muesste (eigentlich auch selten - ich wuerde dann eher auf globale Variablen zurueckgreifen)
Oder wenn man eine Assembler routine in eine Hochsprache wie zB. C einbinden will.
-
In der Tat sollte man die Parameter in den Registern übergeben, wenn es möglich ist. Jedoch stößt man hier schnell an die Grenzen der 80x86-Prozessoren, da die Anzahl der Register doch recht bescheiden ist.
Sind nur wenig Parameter vorhanden(bis 6), so empfiehlt sich die Registerübergabe, ansonsten muss man zwangsläufig auf den Stack ausweichen.
Ciao...
-
Wie könnte man bei Junger Mann's DrawLine Funktion z.B. die Länge variabel machen? Ich hab's mal versucht, aber nicht geschafft z.B. so:
mov ax, 5
call DrawLineund dann in der DrawLine Funktion anstatt der Konstanten ax eingesetzt:
DrawLine PROC NEAR
push bx
xor bx,bx
LineLoop:
mov ah, 0Ch
mov cx, bx ; Splate
mov dx, 80 ; Zeile
mov al, 4 ; rot
int 10h
inc bx
cmp bx, ax ; Hier variable Länge
jl LineLoop
pop bx
ret
DrawLine ENDPAber die Linie ist immer gleich lang, egal was bei ax reinschiebe *g*
Wie geht das?
-
@Trilo:
Das Problem ist, das Du die Länge der Linie in ax an die Funktion übergibst. ax wird aber in der Funktion verändert, sodass Dein Vergleich nicht mehr klappt. Da hilft ein push ax vor mov ah, 0Ch und ein pop ax vor dem Vergleich.
Das ständige Sichern des Registers kostet aber ziemlich viel Zeit. Besser wäre es, ein Register zu nehmen, das nicht benutzt wird, wie z.B. si oder di.
Ciao...
[ Dieser Beitrag wurde am 30.05.2002 um 16:33 Uhr von KalEl editiert. ]
[ Dieser Beitrag wurde am 30.05.2002 um 16:36 Uhr von KalEl editiert. ]
-
Danke KalEl, jetzt funktioniert das mit der Übergabe über das Register, ich habe mich für si entschieden :p
Aber jetzt hab ich das Problem, das ich irgendwie nur Linien hinbekomme bis 255 Pixel Länge. Mach ich z.B.mov si, 300
wird die Linie trotzdem nur 255 Pixel lang. Was kann ich dagegen tun?
-
@Trillo:
Es gibt noch einen kleinen Fehler. Du benutzt Register bx, um die Spalte hochzuzählen. Jedoch wird bh benutzt, um die Bildschirmseite zu bestimmen, in dem der Punkt erscheint. Daher darf auch bx NICHT benutzt werden. Statt bx benutze di.
BIOS-Aufruf 010h, Funktion 0Ch
ah = Funktionsnummer(0Ch)
al = Farbnummer
bh = Bildschirmseite(0...x), x hängt vom Modus ab
cx = Pixelspalte
dx = PixelzeileCiao...
[ Dieser Beitrag wurde am 31.05.2002 um 15:53 Uhr von KalEl editiert. ]
-
hmmm, danke, aber jetzt wird nur ein einziger Pixel gezeichnet
ich poste nochmal den vollständigen code:CODE SEGMENT WORD 'CODE' ASSUME CS:CODE ;---------------------------------------------------------- ; DrawLine Prozedur ;---------------------------------------------------------- DrawLine PROC NEAR push di xor di, di LineLoop: mov ah, 0Ch mov cx, bx ; Splate mov dx, 80 ; Zeile mov al, 4 ; rot int 10h inc di cmp di, si jl LineLoop pop di ret DrawLine ENDP start: ;---------------------------------------------------------- ; In Videomodus 640 * 480 mit 16 Farben wechseln ;---------------------------------------------------------- mov ah, 0 mov al, 12h int 10h ;---------------------------------------------------------- ; Linie zeichnen ;---------------------------------------------------------- mov si, 240 call DrawLine ;---------------------------------------------------------- ; Auf Eingabe eines Zeichens warten ;---------------------------------------------------------- mov ah, 7 int 21h ;---------------------------------------------------------- ; Videomodus zurückschalten ;---------------------------------------------------------- mov ah, 0 mov al, 3h int 10h ;---------------------------------------------------------- ; Programm beenden ;---------------------------------------------------------- mov ah, 04Ch int 21h CODE ENDS END start
-
Hier die bereinigte Version:
DrawLine PROC NEAR push di xor di, di LineLoop: mov ah, 0Ch mov bh, 000h mov cx, di; Splate mov dx, 80 ; Zeile mov al, 4 ; rot int 10h inc di cmp di, si jl LineLoop pop di ret DrawLine ENDP
Ciao...