Program rysujący na ekranie figury geometryczne na podstawie danych umieszczonych w pliku wejściowym o nazwie podawanej przy wywołaniu.
Figury powinny być rysowane w trybach VGA: 320×200-256kol i 640×480-16kol w jednym z czterech kolorów: biały, czerwony, zielony lub niebieski (B,C,Z lub N). Ekran jest traktowany jako pierwsza ćwiartka układu współrzędnych. Początek układu współrzędnych znajduje się w lewym dolnym rogu ekranu.
Dodatkowo w trybie 320×200 figury są wypełniane
Pierwsza linia pliku zawiera tryb ekranu: 320 lub 640
320 – oznacza tryb 320×200
640 – oznacza tryb 640×480
Kolejne linie określają poszczególne figury do wyświetlenia na ekranie. Każda taka linia zawiera na początku literę określającą kolor figury, a następnie ciąg par współrzędnych wierzchołków figury.
Przykład pliku wejściowego: (rysuje czerwony kwadrat i niebieski trójkąt w trybie 320×200):
320
C 0,0 50,0 50,50 0,50
N 100,80 150,110 200,40
Przykład wywołania Programu:
program3 dane.wej
; ver 1.0
.186
;................. Segment danych .................
dane1 segment
p0 dw ?
q0 dw ?
p1 dw ?
q1 dw ?
f_in db 10 dup (?),'0'
uchwyt dw ?
bufor db 1000 dup ('$')
errorx db 'Za duza wspolrzedna X$'
errory db 'Za duza wspolrzedna Y$'
error1 db 'Brak parametru$'
error2 db 'Nie znaleziono pliku$'
error4 db 'Nie mozna zamknac pliku$'
gran_linii dw ?
gran_ekran dw ?
WspX dw ?
WspY dw ?
kop_di dw ?
x dw ?
y dw ?
w1 dw ?
w2 dw ?
a dw ?
b dw ?
dex dw ?
dey dw ?
adx dw ?
ady dw ?
ix dw ?
iy dw ?
du dw ?
dr dw ?
pp dw ?
cp dw ?
kolor db ?
dane1 ends
;..................................................
;................. Segment kodu ...................
code1 segment
ASSUME cs:code1, ds:dane1, ss:stos1
start:
mov ax,seg dane1
mov ds,ax
call CzyParam
call CzytPar
next:
call OtwPlik
call CzytPlik
call Wcz_rozdz
mov di,5 ; tu sie zaczyna pierwszy kolor
call Wcz_kolor
inc di
inc di
jmp startuj
start3:
mov di,[kop_di]
call Wcz_kolor
inc di
inc di
startuj:
call Czytaj ; pierwsza wspolrzedna (dwie liczby), ustawia 'di' na pierwszy znak po ostatniej liczbie
mov ax,[a]
mov [p0],ax
mov [w1],ax
mov ax,[b]
mov [q0],ax
mov [w2],ax
inc di ; przeskocz spacje
call CzyKoniec ; sprawdz, czy doszlismy do konca linii
start2:
call Czytaj ; druga wspolrzedna
mov ax,[a]
mov [p1],ax
mov ax,[b]
mov [q1],ax
call Rysuj_linie
inc di
call CzyKoniec
mov ax,[p1]
mov [p0],ax
mov ax,[q1]
mov [q0],ax
jmp start2
pob_pierw:
mov ax,[w1]
mov [p0],ax
mov ax,[w2]
mov [q0],ax
call Rysuj_linie
mov di,-1
mov ax,[WspX]
dec ax
mov [gran_linii],ax ; gran_linii = WspX - 1
xor bx,bx
jmp szuk_pier
do_nowej_linii:
mov di,[gran_linii]
mov cx,[WspX]
add [gran_linii],cx
xor bx,bx
mov cx,[gran_ekran]
cmp [gran_linii],cx
ja start3 ; gdy dojdziemy do konca, wczytuj nastepna figure
szuk_pier:
inc di
cmp di,[gran_linii]
jae do_nowej_linii
mov al,byte ptr es:[di]
cmp al,[kolor]
jne szuk_pier
mov bx,di ; znacznik pierwszego wystapienia
szuk_drug: ; znaleziono pierwszy punkt
inc di
cmp di,[gran_linii] ; drugi punkt musi byc w tej samej linii ...
ja [do_nowej_linii] ; ... gdy go nie ma, skaczemy do nowej linii
mov al,byte ptr es:[di]
cmp al,[kolor]
je czy_nie_sa_obok ; znaleziono drugi punkt, ale sprawdzamy, czy nie sa obok siebie
jmp szuk_drug
czy_nie_sa_obok:
inc bx
cmp bx,di
je szuk_drug
; dec bx
cmp [WspX],320
je wypelnij_low
call ZamkPlik
call Koniec
wypelnij_low:
mov al,[kolor]
mov byte ptr es:[bx],al
inc bx
cmp bx,di
jne wypelnij_low
jmp do_nowej_linii
;jmp szuk_pier
CzyParam PROC ; sprawdzenie czy sa parametry
mov bx,80h ; sprawdzamy czy istnieje ...
mov cl,byte ptr es:[bx] ; ... jakikolwiek parametr
cmp cl,0 ; jesli nie ma zadnego parametru, to ...
je Komunikat1 ; ... wypisz blad
ret
CzyParam ENDP
CzytPar PROC ; czytanie pierwszego parametru
inc bx ; parametry zaczynaja sie od 82h
mov dl,byte ptr es:[bx] ; wczytujemy znak do dl
cmp dl,0dh
je next
mov f_in[di],dl ; a nastepnie do bufora, ktory bedzie nazwa pliku
inc di
jmp CzytPar
ret
CzytPar ENDP
CzyKoniec PROC ; ------------------ Sprawdz, czy doszlismy do konca linii ------------------------------
mov dl,[bufor+di]
mov [kop_di],di
inc [kop_di]
inc [kop_di]
cmp dl,0dh
je pob_pierw
ret
CzyKoniec ENDP
; wejscie : 'di' - miejsce w pliku
; wyjscie : skok do 'pob_pierw', gdy napotkano na koniec pliku
Wcz_rozdz PROC ; ------------------------- Wczytanie rozdzielczosci ------------------------------------
low_res: ; -- czy 320 x 200 --
mov dl,[bufor]
cmp dl,'3'
jne high_res
mov dl,[bufor+1]
cmp dl,'2'
jne Koniec
mov dl,[bufor+2]
cmp dl,'0'
jne Koniec
mov dl,[bufor+3]
cmp dl,13 ; sprawdzamy, czy jest znak konca linii ...
jne Koniec ; ... gdy nie, wychodzimy (znaczy to, ze jest jeszcze jakas cyfra)
mov [WspX],320
mov [WspY],200
mov [gran_ekran],63999
call InitLow
ret
high_res: ; -- czy 640 x 480 --
mov dl,[bufor]
cmp dl,'6'
jne Koniec
mov dl,[bufor+1]
cmp dl,'4'
jne Koniec
mov dl,[bufor+2]
cmp dl,'0'
jne Koniec
mov dl,[bufor+3]
cmp dl,13 ; sprawdzamy, czy jest znak konca linii ...
jne Koniec ; ... gdy nie, wychodzimy
mov [WspX],640
mov [WspY],480
mov [gran_ekran],307199
call InitHigh
ret
Wcz_rozdz ENDP
Wcz_kolor PROC ; ----------------------------- Wczytanie koloru ----------------------------------------
mov dl,[bufor+di]
cmp dl,'B'
je bialy ; kolor bialy
cmp dl,'C'
je czerwony ; kolor czerwony
cmp dl,'Z'
je zielony ; kolor zielony
cmp dl,'N'
je niebieski ; kolor niebieski
jmp Koniec ; gdy kolor jest niezdefiniowany, wychodzimy
bialy:
mov [kolor],15
ret
czerwony:
mov [kolor],4
ret
zielony:
mov [kolor],2
ret
niebieski:
mov [kolor],1
ret
Wcz_kolor ENDP
Czytaj PROC ; --------- Wczytanie liczb obok przecinka i umieszczenie ich do zmiennych a,b ----------
xor cx,cx
; --------- wczytanie pierwszego punktu do 'cx' ----------
first_p: ; zmienna 'p'
mov al,[bufor+di]
sub al,30h
xor ah,ah ; zamien ascii na cyfre
add cx,ax ; dodaj cyfre do sumy
mov ax,cx ; przenies sume do 'ax'
inc di ; sprawdz nastepny znak
mov dl,[bufor+di] ; ...........
cmp dl,',' ; jesli jest przecinkiem ...
je podstaw ; ... to zakoncz wczytywanie
mov bx,ax ; ... w przeciwnym wypadku pomnoz przez 10 poprzednia liczbe
shl ax,3 ; ax = ax * 8
shl bx,1 ; bx = bx * 2 = ax * 2
add ax,bx ; ax = ax + bx = ax * 10
mov cx,ax
jmp first_p
podstaw:
cmp ax,[WspX]
jae Komunikatx
mov a,ax
inc di
xor cx,cx
; --------- wczytanie drugiego punktu do 'cx' ----------
second_p: ; zmienna 'q'
mov al,[bufor+di]
sub al,30h
xor ah,ah ; zamien ascii na cyfre
add cx,ax ; dodaj cyfre do sumy
mov ax,cx ; przenies sume do 'ax'
inc di ; sprawdz nastepny znak
mov dl,[bufor+di] ; ...........
cmp dl,' ' ; jesli jest spacja
je podstaw2 ; to zakoncz wczytywanie
mov bx,ax ; w przeciwnym wypadku pomnoz przez 10 poprzednia liczbe
shl ax,3 ; 2^3 +
shl bx,1 ; + 2^1
add ax,bx
mov cx,ax
jmp second_p
podstaw2:
cmp ax,[WspY]
jae Komunikaty
mov [b],ax
ret
Czytaj ENDP
InitLow PROC ; -------------------------- Inicjalizacja trybu 320 x 200 x 256 ------------------------
mov ax,0013h
int 10h
mov ax,0A000h
mov es,ax ; es = 0A000h
ret
InitLow ENDP
InitHigh PROC ; -------------------------- Inicjalizacja trybu 640 x 480 x 16 -------------------------
mov ax,0012h
int 10h
mov ax,0a000h
mov es,ax ; es = 0A000h
ret
InitHigh ENDP
RysujPunkt PROC
cmp [WspX],320
je PunktLow
cmp [WspX],640
je PunktHigh
ret
RysujPunkt ENDP
PunktLow: ; ------------------------ Rysowanie punktu o wps. x,y ----------------------------------
mov ax,[y]
neg ax
add ax,199 ; ax = 199 - ax
mov bx,ax ; bx = ax
shl ax,8 ; ax = ax*256
shl bx,6 ; bx = bx*64 = ax*64
add ax,bx ; ax = ax*256 + ax*64 = ax*320 = wiersz*320
add ax,[x] ; ax = wiersz*320 + kolumna = 320y+x
mov di,ax
mov al,[kolor]
mov byte ptr es:[di],al
ret
PunktHigh: ; ------------------------ Rysowanie punktu o wps. x,y ----------------------------------
push cx
mov ax,[x]
mov bx,[y]
neg bx
add bx,479
mov dx,bx
shl bx,6
shl dx,4
add bx,dx ; bx = y * 80
mov dx,ax
shr dx,3 ; dx = x / 8
add bx,dx ; bx = wyliczony adres
mov cl,7
and cl,al ; cl = n (numer bitu w wyznaczonym bajcie w bx)
mov al,80h
shr al,cl ; al = maska
mov dx,3CFh
out dx,al ; wpisujemy do rejestru Bit Mask
mov al,2
mov dx,3C4h
out dx,al ; select map mask register
mov al,0Fh
mov dx,3C5h
out dx,al ; enable all planes
mov al,es:[bx] ; czytanie z pamieci
mov es:[bx],byte ptr 0 ; czyszczenie kolorow
mov al,[kolor]
out dx,al ; ustawianie nowego koloru
mov es:[bx],byte ptr 0FFh ; zapisywanie do pamieci
pop cx
ret
OtwPlik PROC ; ----------------------------- Otwieranie pliku ----------------------------------------
mov ax,3d00h ; otwieramy plik do odczytu
lea dx,[f_in]
int 21h
jc Komunikat2
mov [uchwyt],ax
ret
OtwPlik ENDP
CzytPlik PROC ; ------------------------- Czytanie z pliku do bufora ----------------------------------
mov ax,3f00h
mov bx,[uchwyt]
mov cx,500 ; czytamy..
lea dx,[bufor] ; do bufora
int 21h
ret
CzytPlik ENDP
Rysuj_linie PROC ; ----------------- Rysowanie linii o koncach (p0, q0), (p1, q1) ------------------------
push di
mov ax,[p1]
sub ax,p0
mov [dex],ax ; dex = p1-p0
mov ax,[q1]
sub ax,[q0]
mov [dey],ax ; dey = q1-q0
cmp [dex],0 ; ---- sprawdzanie dex
jge dalej
mov ax,[dex] ; gdy dex < 0
neg ax
mov [adx],ax ; adx = |dex|
jmp spr_y
dalej: ; gdy dex >= 0
mov ax,[dex]
mov [adx],ax ; adx = |dex|
spr_y:
cmp [dey],0 ; ---- sprawdzanie dey
jge dalej2
mov ax,[dey] ; gdy dey < 0
neg ax
mov [ady],ax ; ady = |dey|
jmp nie_spr
dalej2: ; gdy dey >= 0
mov ax,[dey]
mov [ady],ax ; ady = |dey|
nie_spr:
mov ax,[p0]
mov [x],ax ; x = p0
mov ax,[q0]
mov [y],ax ; y = q0
mov [cp],0 ; cp = 0
cmp [dex],0 ; ----- pierwszy if -------
jle dalej3
mov [ix],1 ; if dex > 0 then ix = 1
jmp if_2 ; wyskocz z petli
dalej3:
mov [ix],-1 ; if dex <= 0 then ix = -1
mov [cp],-1 ; cp = -1
if_2: ; ------ drugi if --------
cmp [dey],0
jle dalej4
mov [iy],1 ; if dey > 0 then iy = 1
jmp if_3 ; wyskocz z petli
dalej4:
mov [iy],-1 ; if dey <= 0 then iy = -1
if_3: ; ------ trzeci if -------
mov ax,[adx]
cmp ax,[ady]
jl end_else
mov ax,[ady] ; ------- gdy adx >= ady ---------
add ax,ax ; ax = 2*ady
mov [dr],ax ; dr = 2*ady
mov ax,[adx]
add ax,ax ; ax = 2*adx
mov bx,[dr] ; bx = dr
sub bx,ax ; bx = dr - 2*adx
mov [du],bx ; du = dr - 2*adx
mov ax,[dr]
sub ax,[adx] ; ax = dr - adx
mov [pp],ax ; pp = dr - adx
mov ax,[adx]
inc ax
mov cx,ax
petla_for1:
call RysujPunkt
mov ax,[x]
add ax,[ix]
mov [x],ax ; x = x + ix
mov ax,[pp]
cmp ax,[cp] ; cp nie jest -1
jle if_el
mov ax,[y] ; if pp > cp
add ax,[iy]
mov [y],ax ; y = y + iy
mov ax,[pp]
add ax,[du]
mov [pp],ax ; pp = pp + du
loop petla_for1
pop di
ret
if_el: ; if pp <= cp
mov ax,[pp]
add ax,[dr]
mov [pp],ax ; pp = pp + dr
loop petla_for1
pop di
ret
end_else: ; ------- gdy adx < ady ---------
mov ax,[adx]
add ax,ax
mov [dr],ax ; dr = 2*adx
mov ax,[ady]
add ax,ax ; ax = 2*ady
mov bx,[dr] ; bx = dr
sub bx,ax ; bx = dr - 2*ady
mov [du],bx ; du = dr - 2*ady
mov ax,[dr]
sub ax,[ady] ; ax = dr - ady
mov [pp],ax ; pp = dr - ady
mov ax,ady
inc ax
mov cx,ax
petla_for2:
call RysujPunkt
mov ax,[y]
add ax,[iy]
mov [y],ax ; y = y + iy
mov ax,[pp]
cmp ax,[cp]
jle if_else
mov ax,[x] ; if pp > cp
add ax,[ix]
mov [x],ax ; x = x + ix
mov ax,[pp]
add ax,[du]
mov [pp],ax ; pp = pp + du
loop petla_for2
pop di
ret
if_else: ; if pp <= cp
mov ax,[pp]
add ax,[dr]
mov [pp],ax ; pp = pp + dr
loop petla_for2
pop di
ret
Rysuj_linie ENDP
ZamkPlik PROC ; ------------------------------- Zamykanie pliku ---------------------------------------
mov ax,3e00h
mov bx,[uchwyt]
int 21h
jc Komunikat4
ret
ZamkPlik ENDP
Komunikat1:
lea dx,[error1]
mov ah,9h
int 21h
call Koniec
Komunikat2:
lea dx,[error2]
mov ah,9h
int 21h
call Koniec
Komunikat4:
lea dx,[error4]
mov ah,9h
int 21h
call Koniec
Komunikatx:
mov ax,0003h
int 10h
lea dx,[errorx] ; mov dx,offset error
mov ah,9h
int 21h
call Koniec
Komunikaty:
mov ax,0003h
int 10h
lea dx,[errory] ; mov dx,offset error
mov ah,9h
int 21h
call Koniec
Koniec PROC ; ------------------------------ Procedury koncowe --------------------------------------
; ---------- Czekanie na klawisz -------------
mov ax,0
int 16h
; ---------- Powrot do tr. tekstowego -------------
mov ax,0003h
int 10h
; ---------- Wyjscie do systemu -------------
mov ax,4c00h
int 21h
ret
Koniec ENDP
code1 ends
;..................................................
;................ Segment stosu ...................
stos1 segment stack
dw 1000 dup(?)
stos1 ends
;..................................................
END start