8.2. Чтение и запись логических секторов

Чтение логических секторов осуществляется с помощью команды

int  25h

Перед этой командой надо сформировать следующую информацию:

         DX  – номер логического сектора,  

         AL  – номер дисковода (для A номер равен 0, для B – 1, для C – 2 и т.д.),

         CX  – число секторов, намеченных для чтения,

   DS:BX  – начальный адрес области буфера.

Данная команда аналогична команде int 26h, с помощью которой производится запись из буфера на диск. Если при чтении (или записи) произошла ошибка, то флаг CF устанавливается в 1, регистры AL и AH – будут содержать коды ошибки.

Напишем программу для вывода в шестнадцатеричном виде сектора, номер которого введен с клавиатуры:

< 1 > title     readsect.exe

< 2 > main segment

< 3 > assume    cs:main, ds:data

< 4 > ;чтение сектора и вывод в 16-ном виде на экран

< 5 > extrn     display:near, kbin:near

< 6 > extrn     hex:near, hexw:near, crlf:near

< 7 > lines      equ   16    ;число строк

< 8 > nchar      equ   32    ;число столбцов

< 9 > ;——————————————

< 10 > go:

< 11 > mov       ax,data    ;инициализация

< 12 > mov       ds,ax      ;регистра ds

< 13 > more:

< 14 > mov       dl,’?’     ;подсказка

< 15 > call      display

< 16 > ;——ввод номера сектора——————

< 17 > sub       bx,bx

< 18 > nexsym:

< 19 > call      kbin       ;ввод цифр

< 20 > cmp       al,’ ‘     ;до пробела

< 21 > je back

< 22 > mov       ah,0

< 23 > and       al,00001111b    ;взять цифру

< 24 > mov       di,ax      ;сохранить ax

< 25 > mov       ax,bx      ;число в bx

< 26 > mov       si,10

< 27 > mul       si

< 28 > add       ax,di

< 29 > mov       bx,ax      ;bx=10*bx+цифра

< 30 > loop      nexsym

< 31 > ;——чтение сектора———————-

< 32 > back:

< 33 > mov       dx,bx

< 34 > mov       al,0       ;диск A

< 35 > mov       cx,1       ;один сектор

< 36 > lea       bx,buffer  ;чтение из A

< 37 > int       25h        ;в буфер

< 38 > call      crlf       ;с новой строки

< 39 > ;——вывод на экран———————-

< 40 > lea       bx,buffer

mov   cx,lines

< 1 >

< 2 > mov       si,0

< 3 > newl:

< 4 > push      cx

< 5 > mov       dx,si      ;вывод номера байта

< 6 > push      bx         ;с которого

< 7 > call      hexw       ;начинается строка

< 8 > pop       bx

< 9 > mov       dl,’ ‘

< 10 > call      display

< 11 > mov       di,nchar

< 12 > next:

< 13 > mov       dl,[bx]

< 14 > push      bx

< 15 > call      hex

< 16 > pop       bx

< 17 > inc       bx

< 18 > dec       di

< 19 > jnz       next       ;следующий байт

< 20 > call      crlf

< 21 > add       si,nchar

< 22 > pop       cx         ;новая строка

< 23 > loop      newl

< 24 > call      crlf

< 25 > jmp       more

< 26 > main     ends

< 27 > data     segment

< 28 > buffer   db    lines*nchar dup(?)

< 29 > data     ends

< 30 > end       go

Подпрограммы, вызываемые этой программой, находятся в следующем ниже модуле. (Они будут использоваться и в следующем параграфе.)

< 1 > title     mylib.obj

< 2 > subr segment

< 3 > public    display, kbin, hex, hexw, crlf

< 4 > public    ascii

< 5 > assume     cs:subr, ds:subr

< 6 > ;——подпрограммы—————-

< 7 > ;——вывод символа из dl———

< 8 > display    proc

< 9 > mov       ah,2

< 10 > int       21h

< 11 > ret

< 12 > display  endp

< 13 > ;——ввод символа в al————

< 14 > kbin     proc

< 15 > mov       ah,1

< 16 > int       21h

< 17 > ret

< 18 > kbin     endp

< 19 > ;——вывод байта в 16-ном виде из dl—-

< 20 > hex      proc

< 21 > push      bx         ;сохранение

< 22 > push      ds         ;регистров

< 23 > mov       ax,subr

< 24 > mov       ds,ax

< 25 > push      dx

< 26 > lea       bx,table1

< 27 > mov       ax,0

< 28 > mov       al,dl

< 29 > clc

< 30 > shr       al,1

< 31 > shr       al,1

< 32 > shr       al,1

< 33 > shr       al,1

< 34 > xlat                 ;старший полубайт

< 35 > mov       dl,al

< 36 > call      display

pop   ax

< 1 >

< 2 > and       al,00001111b

< 3 > xlat                 ;младший полубайт

< 4 > mov       dl,al

< 5 > call      display

< 6 > pop       ds         ;восстановление

< 7 > pop       bx         ;регистров

< 8 > ret

< 9 > table1   db    ‘0123456789ABCDEF’

< 10 > hex      endp

< 11 > ;——вывод слова из dx в 16-ном виде

< 12 > hexw     proc

< 13 > push      bx         ;сохранение

< 14 > push      di         ;регистров

< 15 > mov       di,dx

< 16 > mov       dl,dh

< 17 > call      hex        ;старший байт

< 18 > mov       dx,di

< 19 > call      hex

< 20 > mov       dl,’ ‘

< 21 > call      display

< 22 > pop       di         ;восстановление

< 23 > pop       bx         ;регистров

< 24 > ret

< 25 > hexw     endp

< 26 >

< 27 > crlf     proc

< 28 > mov       dl,10

< 29 > call      display

< 30 > mov       dl,13

< 31 > call      display

< 32 > ret

< 33 > crlf     endp

< 34 >

< 35 > ascii    proc        ;вывод из dl в коде ASCII

< 36 > cmp       dl,’a’     ;dl<‘a’?

< 37 > jb l1     ;да

< 38 > cmp       dl,’z’

< 39 > ja l1

< 40 > call      display

< 41 > ret

< 42 > l1:

< 43 > cmp       dl,’0′

< 44 > jb l2

< 45 > cmp       dl,’9′

< 46 > ja l2

< 47 > call      display

< 48 > ret

< 49 > l2:

< 50 > cmp       dl,’A’

< 51 > jb l3

< 52 > cmp       dl,’Z’

< 53 > ja l3

< 54 > call      display

< 55 > ret

< 56 > l3:

< 57 > mov       dl,’.’

< 58 > call      display

< 59 > ret

< 60 > ascii    endp

< 61 > subr     ends

< 62 > end

После выполнения компиляции и сборки:

tasm   readsect

tasm   mylib

tlink  readsect+mylib, readsect

и запуска

readsect

появится подсказка в виде знака ‘?’. Если ввести 0, то будет выведено содержимое загрузочного сектора дискеты A:

? 0

0000    FA33C08EDOBC007C8BF4501FFB1E56FF0E1304A…

и т.д.

Упражнение. С помощью данной программы найти число секторов на дорожке и число записей в корневом каталоге. Посмотреть таблицу FAT.