A következő program beolvas egy (Floppy)lemezről egy (512 byte-os) szektort. Lényegében egy házi feladat volt az egyetemen, hogy csinosítsuk ki keretekkel, esetleg menükkel a programot, ami már előre meg volt írva. Ezen célon túllőve nem csak a kimenetet csinosítottam, hanem a forráskódot is. Jóllehet, túl is bonyolítottam.
Az igazsághoz hozzá tartozik, hogy a program csak floppy lemezről tud beolvasni. 3 féle megoldást próbáltam ki a lemezszektor olvasásra, de némi utánajárás után kiderült, hogy vagy az oprendszer nem támogatja a módszert, vagy a fájlrendszer. Nem beszélve arról, hogy egy virtuális FAT12 -es merevlemezt sem tudtam olvasni, tehát maradt konkrétan a virtuális floppy csatolás virtualboxban egy virtuális XP-vel. Floppy képet egyébként készen is lehet letölteni a neten.
Erre azért volt szükség, mert nincs már a gépemben floppy meghajtó. Hozzáteszem az egyetemen sincs azon a gépen, ahol be kellett mutatni a programot. Így persze senki nem tudta élesben bemutatni, csak aki laptop-ot vitt, és a fent leírt virtuális módszert használva saját gépén bírta működésre a lemezolvasót. Nekünk, többieknek maradt az "ignore" gomb nyomogatása, amikor a windows felszólított, hogy nincs mit olvasni. Így a memóriából valami szemetet kiírva a képernyőre lett bemutatva a program.
De nézzük akkor a programot, ami letölthető a következő linken is: Letöltés
.stack
.data
hexaPosX = 5
posY = 3
charRelPosX = 5
rows = 15
;-------------------------
hexaWidth = 47 ;3*16-1, mert az utolso hexa utan nem kell space
charWidth = 16
borderWidth = hexaWidth+charRelPosX+charWidth+2
charPosX = hexaPosX+hexaWidth+charRelPosX
;------------------------------
ESCAPE = 27
cr = 13 ;carrige return (kocsi vissza)
lf = 10 ;line feed (uj sor)
space = ' '
maxRows = 512 / 16
lastPageRows = maxRows mod rows
maxPage = (maxRows / rows) + ((lastPageRows+(rows-1)) / rows )
dcrlf db cr,lf,0 ;uj sor
goodbye db 'Szep napot! Hasznalj maskor is!!',0
goodbyeLength = $-goodbye-1
borderTop db 201, hexaWidth + (charRelPosX/2) dup(205), 203,
(charRelPosX/2) + charWidth dup(205), 187,0
borderMiddle db 186
borderBottom db 200, hexaWidth + (charRelPosX/2) dup(205) ,202,
(charRelPosX/2) + charWidth dup(205) , 188,0
pagenum db 0
offs dw 0
txtPage db 'Oldal: ',0
txtDiskId db 'Lemez:',0
txtBlockNumber db 'Block szama:',0
quit db 0
.data?
block db 512 dup(?)
.code
writem_char macro chr ;atadott karakter kiirasa kepernyore
push dx
mov dl, chr
call write_char
pop dx
endm
writem macro string ;atadott karakter kiirasa kepernyore
push bx
lea bx, string
call write_string
pop bx
endm
gotoXY macro x, y ;kurzor pozicionalasa x, y pozicioba (x=oszlop, y=sor)
push dx ;hasznalt regiszterek mentese
push ax
push bx
mov dh, y ;dh-ba kell kerulnie az sorszamnak
mov dl, x ;es dl-be kell kerulni a oszlopszamnak
mov ah, 2h ;A kettes kod a kurzor pozicionalasa
xor bh, bh ;Hasznalt kepernyo lap szama 0
int 10h ;képernyő driver hivasa
pop bx ;regiszterek visszatoltese
pop ax
pop dx
endm
gotoXYRel macro x, y
push dx ;hasznalt regiszterek mentese
push ax
push bx
push cx
mov ah, 03h
xor bh, bh
int 10h
add dh, y ;dh-ba kell kerulnie az sorszamnak
add dl, x ;es dl-be kell kerulni a oszlopszamnak
mov ah, 2h ;A kettes kod a kurzor pozicionalasa
xor bh, bh ;Hasznalt kepernyo lap szama 0
int 10h ;képernyő driver hivasa
pop cx
pop bx ;regiszterek visszatoltese
pop ax
pop dx
endm
writeto macro string, x, y ;szoveg kiirasa x, y pozicioba
gotoxy x, y ;eloszor pozicionalas
writem string ;majd kiiras
endm
read_char proc uses ax ;egy karakter beolvasasa
mov ah, 1 ;karakter bekeres kodja
int 21h ;hexa 21 -es megszakitas DOS-funkciok hivasahoz
;A karakter ekkor AL regiszterbe kerül
mov dl, al ;A karakter-t a DL regiszterbe tesszuk
ret ;visszateres subrutinbol
read_char endp
;dl-ben levo kezdocimtol string kiirasa
write_string proc uses bx dx
.while byte ptr [bx] != 0
mov dl, [bx]
call write_char
inc bx
.endw
ret
write_string endp
;dl-ben varja mit kell kiirni
write_char proc uses ax
mov ah, 2h ; Kiiras kodja
int 21h
ret
write_char endp
;adatszegmens inicializalasa
dsinit proc uses ax
mov ax, dgroup ;adatszegmens kezdocime ax-be
mov ds, ax ;ezt betoltjuk az adatszegmens regiszterbe
ret
dsinit endp
;DOS kepernyo torlese
clrscr proc uses ax
mov ax, 3 ;3-as bekerul ah-ba. Utasitas kepernyo torlesere
int 10h ;hexa 10-es megszakitas. Kepernyo driver hivasara
ret
clrscr endp
;sortores
linebreak proc
writem dcrlf
ret
linebreak endp
lcase proc
.if (dl >= "A" && dl <= "Z")
add dl, "a"-"A"
.endif
ret
lcase endp
read_block proc uses ax bx cx dx
writeto txtDiskId, 26, 6
writeto txtBlockNumber, 20, 7
gotoXY 33, 6
call read_char
.if dl == ESCAPE
mov quit, 1
ret
.endif
call lcase
sub dl, 'a'
mov al, dl
gotoXY 33, 7
call read_decimal
lea bx, block
mov cx, 1 ;beolvasando blokkok száma
int 25h
popf
ret
read_block endp
out_line_hexa proc uses bx cx dx
mov cx, 16
.repeat
mov dl, block[bx]
call write_hexa
mov dl, space
call write_char
inc bx
.untilcxz
ret
out_line_hexa endp
out_line_char proc uses bx cx dx
mov cx, 16
.repeat
mov dl, block[bx]
.if dl < space
mov dl, space
.endif
call write_char
inc bx
.untilcxz
ret
out_line_char endp
init_write_block proc
.if pagenum == (maxPage-1) && lastPageRows
mov cx, lastPageRows
.else
mov cx, rows
.endif
add bx, offs
ret
init_write_block endp
write_block_hexa proc uses cx bx
call init_write_block
.repeat
gotoXYRel hexaPosX, 0
call out_line_hexa
call linebreak
add bx, 16
.untilcxz
ret
write_block_hexa endp
write_block_char proc uses cx bx
call init_write_block
.repeat
gotoXYRel charPosX, 0
call out_line_char
call linebreak
add bx, 16
.untilcxz
ret
write_block_char endp
write_hexa_digit proc uses dx
.if dl >= 10
add dl, 'A'-'0'-10
.endif
add dl, '0'
call write_char
ret
write_hexa_digit endp
write_hexa proc uses cx dx
mov dh, dl
mov cl, 4
shr dl, cl
call write_hexa_digit
mov dl, dh
and dl, 0Fh
call write_hexa_digit
ret
write_hexa endp
read_decimal proc uses ax bx
mov bx, 10
xor ax, ax
xor dx, dx
.while 1
call read_char
.break .if dl == cr
sub dl, '0'
mul bl
add ax, dx
.endw
mov dx, ax
ret
read_decimal endp
write_decimal proc uses ax dx cx si
mov ax, dx
mov si, 10 ; 10-el osztjuk si-t
xor cx, cx ; cx torlese
.while ax != 0
xor dx, dx
div si
push dx
inc cx
.endw
.repeat
pop dx
call write_hexa_digit
.untilcxz
ret
write_decimal endp
readCmdKey proc
mov ah, 00h
int 16h
ret
readCmdKey endp
pager proc uses dx ax
.if al == 0
.if (ah == 'H' && pagenum >= 1)
dec pagenum
.elseif (ah == 'P' && pagenum < (maxPage-1))
inc pagenum
.endif
mov ax, rows*16
mul word ptr pagenum
mov offs, ax
.endif
ret
pager endp
hideCursor proc uses ax cx dx bx
mov ah, 03h
int 10h
or ch, 30h
mov ah, 1
int 10h
ret
hideCursor endp
goodbyeProc proc uses ax
call clrscr
call hideCursor
mov al, goodByelength
shr al, 1
mov ah, 40
sub ah, al
gotoXY ah, 12
writem goodbye
ret
goodbyeProc endp
writeInfo proc uses dx bx
;oldal info
writem txtPage
xor dx, dx
mov dl, maxPage
call write_decimal
writem_char '/'
;oldalszam
mov dl, pagenum
inc dl
call write_decimal
ret
writeInfo endp
drawBorder proc uses cx ax
;felso keret
gotoXY hexaPosX-1, posY-1
writem borderTop
;kozepso resz
mov cx, rows
mov al, posY
.repeat
gotoXY hexaPosX-1,al
writem_char borderMiddle
gotoXY hexaPosX+hexaWidth+(charRelPosX/2), al
writem_char borderMiddle
gotoXY hexaPosX+borderWidth-2, al
writem_char borderMiddle
inc al
.untilcxz
;keret alja
gotoXY hexaPosX-1, al
writem borderBottom
inc al
;keret alatti informacios sav
gotoXY hexaPosX, al
call writeInfo
gotoXY 0, 0
ret
drawBorder endp
run_read_block proc uses ax
call read_block
.if quit == 1
ret
.endif
mov pagenum, 0
.repeat
call clrscr
call hideCursor
call drawBorder
gotoXYRel 0, posY
call write_block_hexa
.if pagenum == (maxPage-1) && lastPageRows
gotoXYRel 0, -lastPageRows
.else
gotoXYRel 0, -rows
.endif
call write_block_char
call readCmdKey
call pager
gotoXY 0, 0
.until al == ESCAPE
ret
run_read_block endp
main proc
call dsinit
call clrscr
call hideCursor
;comment *
.repeat
.break .if quit == 1
call clrscr
call run_read_block
.until al == ESCAPE
call goodbyeProc
call readCmdKey
;*
.exit
main endp
end main
Most túl sokat nem kommentálnám. A forráskódban sem hagytam sok megjegyzést. Akit érdekel, kipróbálhatja. Meg persze kérdezni lehet. De nem hiszem, hogy sokan ütik el a drága idejüket assembly forráskódok tanulmányozásával :)
A programban a szektor megjelenítésnél le és fel nyilakkal lehet lapozni. ESC -re kilép a lemez betűjel és szektor szám ( hányadik szektor ) bekéréshez. Újabb ESC-re pedig kilép a programból. Persze előbb illedelmesen elköszön.