Punkt zeichnen (int 10, al 0Ch)
-
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...