MASM lemezszektor olvasó lapozható tartalommal

Előkép

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.



Adatbekérés

Kiírás

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

  1. .model small
  2.  
  3. .stack
  4.  
  5. .data    
  6.     hexaPosX = 5
  7.     posY = 3
  8.     charRelPosX = 5
  9.     rows = 15
  10.    
  11.     ;-------------------------
  12.     hexaWidth = 47 ;3*16-1, mert az utolso hexa utan nem kell space
  13.     charWidth = 16
  14.     borderWidth = hexaWidth+charRelPosX+charWidth+2
  15.     charPosX = hexaPosX+hexaWidth+charRelPosX
  16.     ;------------------------------
  17.     ESCAPE = 27
  18.     cr = 13     ;carrige return (kocsi vissza)
  19.     lf = 10     ;line feed (uj sor)
  20.     space = ' '
  21.    
  22.     maxRows = 512 / 16
  23.     lastPageRows = maxRows mod rows
  24.     maxPage = (maxRows / rows) + ((lastPageRows+(rows-1)) / rows )
  25.    
  26.     dcrlf db cr,lf,0   ;uj sor
  27.     goodbye db 'Szep napot! Hasznalj maskor is!!',0
  28.     goodbyeLength = $-goodbye-1
  29.     borderTop db 201, hexaWidth + (charRelPosX/2) dup(205), 203,
  30.                       (charRelPosX/2) + charWidth dup(205), 187,0
  31.     borderMiddle db 186
  32.     borderBottom db 200, hexaWidth + (charRelPosX/2) dup(205) ,202,
  33.                      (charRelPosX/2) + charWidth dup(205) , 188,0
  34.     pagenum db 0
  35.     offs dw 0
  36.    
  37.     txtPage db 'Oldal: ',0
  38.     txtDiskId db 'Lemez:',0
  39.     txtBlockNumber db 'Block szama:',0
  40.    
  41.     quit db 0
  42.    
  43. .data?
  44.     block db 512 dup(?)
  45. .code
  46.  
  47. writem_char macro chr    ;atadott karakter kiirasa kepernyore
  48.     push dx
  49.    
  50.     mov dl, chr
  51.     call write_char
  52.    
  53.     pop dx
  54. endm
  55.  
  56. writem macro string       ;atadott karakter kiirasa kepernyore
  57.     push bx
  58.    
  59.     lea bx, string
  60.     call write_string
  61.    
  62.     pop bx
  63. endm
  64.  
  65. gotoXY macro x, y       ;kurzor pozicionalasa x, y pozicioba (x=oszlop, y=sor)
  66.     push dx             ;hasznalt regiszterek mentese
  67.     push ax
  68.     push bx
  69.  
  70.     mov dh, y           ;dh-ba kell kerulnie az sorszamnak
  71.     mov dl, x           ;es dl-be kell kerulni a oszlopszamnak
  72.     mov ah, 2h          ;A kettes kod a kurzor pozicionalasa
  73.  
  74.     xor bh, bh          ;Hasznalt kepernyo lap szama 0
  75.     int 10h             ;képernyő driver hivasa
  76.  
  77.     pop bx              ;regiszterek visszatoltese
  78.     pop ax
  79.     pop dx
  80. endm
  81.  
  82. gotoXYRel macro x, y
  83.     push dx             ;hasznalt regiszterek mentese
  84.     push ax
  85.     push bx
  86.     push cx
  87.  
  88.     mov ah, 03h
  89.     xor bh, bh
  90.     int 10h
  91.  
  92.     add dh, y           ;dh-ba kell kerulnie az sorszamnak
  93.     add dl, x           ;es dl-be kell kerulni a oszlopszamnak
  94.     mov ah, 2h          ;A kettes kod a kurzor pozicionalasa
  95.  
  96.     xor bh, bh          ;Hasznalt kepernyo lap szama 0
  97.     int 10h             ;képernyő driver hivasa
  98.  
  99.     pop cx
  100.     pop bx              ;regiszterek visszatoltese
  101.     pop ax
  102.     pop dx
  103. endm
  104.  
  105. writeto macro string, x, y ;szoveg kiirasa x, y pozicioba
  106.     gotoxy x, y            ;eloszor pozicionalas
  107.     writem string          ;majd kiiras
  108. endm
  109.  
  110. read_char proc uses ax  ;egy karakter beolvasasa
  111.     mov ah, 1           ;karakter bekeres kodja
  112.     int 21h             ;hexa 21 -es megszakitas DOS-funkciok hivasahoz
  113.                         ;A karakter ekkor AL regiszterbe kerül
  114.     mov dl, al          ;A karakter-t a DL regiszterbe tesszuk
  115.     ret                 ;visszateres subrutinbol
  116. read_char endp
  117.  
  118. ;dl-ben levo kezdocimtol string kiirasa
  119. write_string proc uses bx dx
  120.     .while byte ptr [bx] != 0
  121.       mov dl, [bx]
  122.       call write_char
  123.       inc bx
  124.     .endw
  125.     ret
  126. write_string endp
  127.  
  128. ;dl-ben varja mit kell kiirni
  129. write_char proc uses ax
  130.     mov ah, 2h  ; Kiiras kodja
  131.     int 21h
  132.     ret
  133. write_char endp
  134.  
  135. ;adatszegmens inicializalasa
  136. dsinit proc uses ax  
  137.     mov ax, dgroup   ;adatszegmens kezdocime ax-be
  138.     mov ds, ax       ;ezt betoltjuk az adatszegmens regiszterbe
  139.     ret
  140. dsinit endp
  141.  
  142. ;DOS kepernyo torlese
  143. clrscr proc uses ax
  144.     mov ax, 3  ;3-as bekerul ah-ba. Utasitas kepernyo torlesere
  145.     int 10h    ;hexa 10-es megszakitas. Kepernyo driver hivasara
  146.     ret
  147. clrscr endp
  148.  
  149. ;sortores
  150. linebreak proc
  151.     writem dcrlf
  152.     ret
  153. linebreak endp
  154.  
  155. lcase proc
  156.     .if (dl >= "A" && dl <= "Z")
  157.         add dl, "a"-"A"
  158.     .endif
  159.     ret
  160. lcase endp
  161.  
  162. read_block proc uses ax bx cx dx
  163.  
  164.     writeto txtDiskId, 26, 6
  165.     writeto txtBlockNumber, 20, 7
  166.    
  167.     gotoXY 33, 6
  168.     call read_char
  169.     .if dl == ESCAPE
  170.         mov quit, 1
  171.         ret
  172.     .endif
  173.     call lcase
  174.     sub dl, 'a'
  175.     mov al, dl
  176.  
  177.     gotoXY 33, 7
  178.     call read_decimal
  179.  
  180.     lea bx, block
  181.     mov cx, 1 ;beolvasando blokkok száma  
  182.     int 25h
  183.     popf
  184.     ret
  185. read_block endp
  186.  
  187. out_line_hexa proc uses bx cx dx
  188.     mov cx, 16
  189.     .repeat
  190.         mov dl, block[bx]
  191.         call write_hexa
  192.         mov dl, space
  193.         call write_char
  194.         inc bx
  195.     .untilcxz
  196.     ret
  197. out_line_hexa endp
  198.  
  199. out_line_char proc uses bx cx dx
  200.     mov cx, 16
  201.     .repeat
  202.         mov dl, block[bx]
  203.         .if dl < space
  204.             mov dl, space
  205.         .endif
  206.         call write_char
  207.         inc bx
  208.     .untilcxz
  209.     ret
  210. out_line_char endp
  211.  
  212. init_write_block proc
  213.     .if pagenum == (maxPage-1) && lastPageRows
  214.         mov cx, lastPageRows
  215.     .else
  216.         mov cx, rows
  217.     .endif
  218.     add bx, offs
  219.     ret
  220. init_write_block endp
  221.  
  222. write_block_hexa proc uses cx bx
  223.     call init_write_block
  224.     .repeat
  225.         gotoXYRel hexaPosX, 0
  226.         call out_line_hexa
  227.         call linebreak
  228.         add bx, 16
  229.     .untilcxz  
  230.     ret
  231. write_block_hexa endp
  232.  
  233. write_block_char proc uses cx bx
  234.     call init_write_block
  235.     .repeat
  236.         gotoXYRel charPosX, 0
  237.         call out_line_char
  238.         call linebreak
  239.         add bx, 16
  240.     .untilcxz  
  241.     ret
  242. write_block_char endp
  243.  
  244. write_hexa_digit proc uses dx
  245.     .if dl >= 10
  246.         add dl, 'A'-'0'-10
  247.     .endif
  248.     add dl, '0'        
  249.     call write_char
  250.     ret
  251. write_hexa_digit endp
  252.  
  253. write_hexa proc uses cx dx
  254.     mov dh, dl
  255.     mov cl, 4
  256.     shr dl, cl
  257.     call write_hexa_digit
  258.     mov dl, dh
  259.     and dl, 0Fh
  260.     call write_hexa_digit
  261.  
  262.     ret
  263. write_hexa endp
  264.  
  265. read_decimal proc uses ax bx
  266.     mov bx, 10
  267.     xor ax, ax
  268.     xor dx, dx
  269.    
  270.     .while 1
  271.         call read_char
  272.         .break .if dl == cr
  273.         sub dl, '0'
  274.         mul bl
  275.         add ax, dx
  276.     .endw
  277.     mov dx, ax
  278.     ret
  279. read_decimal endp
  280.  
  281. write_decimal proc uses ax dx cx si
  282.     mov ax, dx
  283.     mov si, 10   ; 10-el osztjuk si-t
  284.  
  285.     xor cx, cx   ; cx torlese
  286.  
  287.     .while ax != 0
  288.         xor dx, dx
  289.         div si
  290.         push dx
  291.         inc cx
  292.     .endw
  293.  
  294.     .repeat
  295.         pop dx
  296.         call write_hexa_digit
  297.     .untilcxz
  298.     ret
  299. write_decimal endp
  300.  
  301. readCmdKey proc
  302.     mov ah, 00h
  303.     int 16h
  304.     ret
  305. readCmdKey endp
  306.  
  307. pager proc uses dx ax
  308.     .if al == 0
  309.       .if (ah == 'H' && pagenum >= 1)
  310.          dec pagenum
  311.       .elseif (ah == 'P' && pagenum < (maxPage-1))
  312.          inc pagenum
  313.       .endif
  314.        mov ax, rows*16
  315.        mul word ptr pagenum
  316.        mov offs, ax
  317.     .endif  
  318.     ret
  319. pager endp
  320.  
  321.  
  322. hideCursor proc uses ax cx dx bx
  323.     mov ah, 03h
  324.     int 10h
  325.     or ch, 30h
  326.     mov ah, 1
  327.     int 10h
  328.     ret
  329. hideCursor endp
  330.  
  331. goodbyeProc proc uses ax
  332.     call clrscr
  333.     call hideCursor
  334.     mov al, goodByelength
  335.     shr al, 1
  336.     mov ah, 40
  337.     sub ah, al
  338.     gotoXY ah, 12
  339.     writem goodbye
  340.     ret
  341. goodbyeProc endp
  342.  
  343. writeInfo proc uses dx bx
  344.  
  345.     ;oldal info
  346.     writem txtPage
  347.     xor dx, dx
  348.     mov dl, maxPage
  349.     call write_decimal
  350.     writem_char '/'
  351.     ;oldalszam
  352.     mov dl, pagenum
  353.     inc dl
  354.     call write_decimal
  355.     ret
  356. writeInfo endp
  357.  
  358. drawBorder proc uses cx ax
  359.     ;felso keret
  360.     gotoXY hexaPosX-1, posY-1
  361.     writem borderTop
  362.     ;kozepso resz
  363.     mov cx, rows
  364.     mov al, posY
  365.     .repeat
  366.        gotoXY hexaPosX-1,al
  367.        writem_char borderMiddle
  368.        gotoXY hexaPosX+hexaWidth+(charRelPosX/2), al
  369.        writem_char borderMiddle
  370.        gotoXY hexaPosX+borderWidth-2, al
  371.        writem_char borderMiddle
  372.        inc al
  373.     .untilcxz
  374.     ;keret alja
  375.     gotoXY hexaPosX-1, al
  376.     writem borderBottom
  377.     inc al
  378.     ;keret alatti informacios sav
  379.     gotoXY hexaPosX, al
  380.     call writeInfo
  381.    
  382.     gotoXY 0, 0
  383.     ret
  384. drawBorder endp
  385.  
  386. run_read_block proc uses ax
  387.     call read_block
  388.     .if quit == 1
  389.         ret
  390.     .endif
  391.     mov pagenum, 0
  392.     .repeat
  393.         call clrscr
  394.         call hideCursor
  395.         call drawBorder
  396.         gotoXYRel 0, posY
  397.         call write_block_hexa
  398.         .if pagenum == (maxPage-1) && lastPageRows
  399.             gotoXYRel 0, -lastPageRows
  400.         .else
  401.             gotoXYRel 0, -rows
  402.         .endif
  403.         call write_block_char                                  
  404.         call readCmdKey
  405.         call pager
  406.         gotoXY 0, 0
  407.     .until al == ESCAPE
  408.    ret
  409. run_read_block endp
  410.  
  411. main proc
  412.     call dsinit
  413.     call clrscr
  414.     call hideCursor
  415.    
  416.     ;comment *
  417.     .repeat
  418.     .break .if quit == 1
  419.         call clrscr
  420.         call run_read_block
  421.     .until al == ESCAPE
  422.     call goodbyeProc
  423.     call readCmdKey
  424.     ;*
  425.    
  426.     .exit
  427. main endp
  428.  
  429. 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.

Kategóriák: 
Megosztás/Mentés

Új hozzászólás