Питер Абель. Ассемблер и программирование для IBM PC

страница №15

LEA SI,ASCWAGE+7 ;Установить дес. точку
MOV BYTE PTR[SI],'.'
ADD SI,NODEC ;Установить правую позицию
G30:
CMP BYTE PTR[SI],'.'
JNE G35 ;Обойти, если дес.поз.
DEC SI
G35:
CMP DX,00 ;Если dx:ax < 10,
JNZ G40
CMP AX,0010 ; то операция завершена
JB G50
G40:
DIV TENWD ;Остаток - ASCII-цифра
OR DL,30H
MOV [SI],DL ;Записать ASCII символ
DEC SI
SUB DX,DX ;Стереть остаток
JMP G30
G50:
OR AL,30H ;Записать последний ASCII
MOV [SI],AL ; символ
RET
G10WAGE ENDP
; Вывод величины оплаты:
; ---------------------
K10DISP PROC
MOV COL,50 ;Установить столбец
CALL Q20CURS
MOV CX,09
LEA SI,ASCWAGE
K20: ;Стереть лидирующие нули
CMP BYTE PTR[SI],30H
JNE K30 ; пробелами
MOV BYTE PTR[SI],20H
INC SI
LOOP K20
K30:
LEA DX,MESSG3 ;Вывод на экран
MOV AH,09
INT 21H
CMP ROW,20 ;Последняя строка экрана?
JAE K80
INC ROW ; нет - увеличить строку
JMP K90
K80:
MOV AX,0601H ; да --
CALL Q10SCR ; прокрутить и
MOV COL,00 ; установить курсор
CALL Q20CURS
K90: RET
K10DISP ENDP
; Преобразование ASCII-чисел



Ассемблер для IBM PC. Программы. 94


; в двоичное представление:
; --------------------------
M10ASBI PROC
MOV MULT10,0001
MOV BINVAL,00
MOV DECIND,00
SUB BX,BX
M20:
MOV AL,[SI] ;ASCII-символ
CMP AL,'.' ;Обойти, если дес.точка
JNE M40
MOV DECIND,01
JMP M90
M40:
AND AX,000FH
MUL MULT10 ;Умножить на фактор
ADD BINVAL,AX ;Сложить с дв.значением
MOV AX,MULT10 ;Вучислить следующий
MUL TENVD ; фактор x 10
MOV MULT10,AX
CMP DECIND,00 ;Десятичная точка?
JNZ M90
INC BX ; да - обойти точку
M90:
DEC SI
LOOP M20
;Конец цикла
CMP DECIND,00 ;Была дес.точка?
JZ M100 ; да --
ADD NODEC,BX ; сложить с итогом
M100: RET
M10ASBI ENDP
; Прокрутка экрана:
; ----------------
Q10SCR PROC NEAR ;AX установлен при вызове
MOV BH,30 ;Цвет (07 для ч/б)
SUB CX,CX
MOV DX,184FH
INT 10H
RET
Q10SCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02
SUB BH,BH
MOV DH,ROW
MOV DL,COL
INT 10H
RET
Q20CURS ENDP

CODESG ENDS



Ассемблер для IBM PC. Программы. 95


END BEGIN























































Ассемблер для IBM PC. Программы. 96



page 60,132
TITLE DIRECT (COM) Прямой табличный доступ
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; ------------------------------------------------
THREE DB 3
MONIN DB '11'
ALFMON DB '???','$'
MONTAB DB 'JAN','FEB','MAR','APR','MAY','JUN'
DB 'JUL','AUG','SEP','OKT','NOV','DEC'
; ------------------------------------------------
MAIN PROC NEAR ;Основная процедура
CALL C10CONV ;Получить двоичное значение
CALL D10LOC ;Выделить месяц из таблицы
CALL F10DISP ;Выдать месяц на экран
RET
MAIN ENDP
; Перевод ASCII в двоичное представление:
; --------------------------------------
C10CONV PROC
MOV AH,MONIN ;Загрузить номер месяца
MOV AL,MONIN+1
XOR AX,3030H ;Удалить ASCII тройки
CMP AH,00 ;Месяц 01-09?
JZ C20 ; да - обойти
SUB AH,AH ; нет - очистить AH,
ADD AL,10 ; и перевести в двоичное
C20 RET
C10CONV ENDP
; Выделение месяца из таблицы:
; ---------------------------
D10LOC PROC
LEA SI,MONTAB
DEC AL ;Коррекция для таблицы
MUL THREE ;Умножить AL на 3
ADD SI,AX
MOV CX,03 ;Трехсимвольная пересылка
CLD
LEA DI,ALFMON
REP MOVSB ;Переслать 3 символа
RET
D10LOC ENDP
; Вывод на экран симв.месяца:
; --------------------------
F10DISP PROC
LEA DX,ALFMON
MOV AH,09
INT 21H
RET
F10DISP ENDP



Ассемблер для IBM PC. Программы. 97



CODESG ENDS
END BEGIN





















































Ассемблер для IBM PC. Программы. 98



page 60,132
TITLE TABSRCH (COM) Табличный поиск
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; -----------------------------------------------
STOKNIN DW '23'
STOKTAB DB '05','Excavators'
DB '08','Lifters '
DB '09','Presses '
DB '12','Valves '
DB '23','Processors'
DB '27','Pumps '
DESCRN 10 DUP(?)
; -----------------------------------------------
MAIN PROC NEAR
MOV AX,STOKNIN ;Загрузить номер элемента
XCHG AL,AH
MOV CX,06 ;Число элементов в таблице
LEA SI,STOKTAB ;Начальный адрес таблицы
A20:
CMP AX,[SI] ;Сравнить элементы
JE A30 ;Если равны - выйти,
ADD SI,12 ; нет - следующий элемент
LOOP A20
CALL R10ERR ;Элемент в таблице не найден
RET
A30:
MOV CX,05 ;Длина описания элемента
LEA DI,DESCRN ;Адрес описания элемента
INC SI
INC SI ;Выделить описание
REP MOVSW ; из таблицы
RET
MAIN ENDP
;
R10ERR PROC
; <Вывод сообщения об ошибке>
RET
R10ERR ENDP

CODESG ENDS
END BEGIN











Ассемблер для IBM PC. Программы. 99



page 60,132
TITLE TABSRCH (COM) Табличный поиск, использующий CMPSB
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; ----------------------------------------------------
STOKNIN DW '123'
STOKTAB DB '035','Excavators' ;Начало таблицы
DB '038','Lifters '
DB '049','Presses '
DB '102','Valves '
DB '123','Processors'
DB '127','Pumps '
DB '999', 10 DUP(' ') ;Конец таблицы
DESCRN 10 DUP(?)
; ----------------------------------------------------
MAIN PROC NEAR
CLD
LEA SI,STOKTAB ;Начальный адрес таблицы
A20:
MOV CX,03 ;Сравнивать по 3 байта
LEA DI,STOKNIN ;Адрес искомого элемента
REPE CMPSB ;Сравнение
JE A30 ;Если равно - выйти,
JA A40 ;если больше - нет в таблице
ADD SI,CX ;Прибавить CX к адресу
JMP A20 ;Следующий элемент таблицы
A30:
MOV CX,05 ;Пересылать 5 слов
LEA DI,DESCRN ;Адрес описания
REP MOVSV ;Переслать из таблицы
RET
A40:
CALL R10ERR ;элемент в таблице не найден
RET
MAIN ENDP

R10ERR PROC
; <Вывод на экран сообщения об ошибке>
RET
R10ERR ENDP

CODESG ENDS
END BEGIN










Ассемблер для IBM PC. Программы. 100



page 60,132
TITLE XLATE (COM) Перевод кода ASCII в код EBCDIC
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
; ----------------------------------------------------
ASCNO DB '-31.5'
EBCNO DB 6 DUP(' ')
XLTAB DB 45 DUP(40H)
DB 60H, 2DH
DB 5CH
DB 0F0H,0F1H,0F2H,0F3H,0F4H
DB 0F5H,0F6H,0F7H,0F8H,0F9H
DB 199 DUP(40H)
; ----------------------------------------------------
MAIN PROC NEAR ;Основная процедура
LEA SI,ASCNO ;Адрес символов ASCNO
LEA DI,EBCNO ;Адрес поля EBCNO
MOV CX,06 ;Длина
LEA BX,XLTAB ;Адрес таблицы
A20:
MOV AL,[SI] ;Получить ASCII символ
XLAT ;Перекодировка
MOV [DI],AL ;Записать в поле EBCNO
INC DI
INC SI
LOOP A20 ;Повторить 6 раз
RET
MAIN ENDP
CODESG ENDS
END BEGIN























Ассемблер для IBM PC. Программы. 101



page 60,132
TITLE ASCHEX (COM) Преобразование ASCII в шест.
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
; -----------------------------------------------
DISPROW DB 16 DUP(' '), 13
HEXSTR DB 00
XLATAB DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
; -----------------------------------------------
MAIN PROC NEAR ;Основная процедура
CALL Q10CLR ;Очистить экран
LEA SI,DISPROW
A20LOOP:
CALL C10HEX ;Перекодировать
CALL D10DISP ; и вывести на экран
CMP HEXCTR,0FFH ;Последнее значение (FF)?
JE A50 ; да - завершить
INC HEXCTR ; нет - перейти к следующему
JMP A20LOOP
A50: RET
MAIN ENDP

C10HEX PROC NEAR ;Перекодировка в шест.
MOV AH,00
MOV AL,HEXCTR ;Получить шест.пару
SHR AX,CL ;Сдвиг правой шест.цифры
LEA BX,XLATAB ;Установить адрес таблицы
MOV CL,04 ;Установить величину сдвига
XLAT ;Перекодировка в шест.
MOV [SI],AL ;Записать левый символ

MOV AL,HEXCTR
SHL AX,CL ;Сдвиг левой цифры
XLAT
MOV [SI]+1,AL ;Перекодировка в шест.
RET ;Записать правый символ
C10HEX ENDP

D10DISP PROC NEAR ;Вывод на экран
MOV AL,HEXCTR
MOV [SI]+3,AL
CMP AL,1AH ;Символ EOF?
JE D20 ; да - обойти
CMP AL,07H ;Меньше/равно 08?
JB D30 ; да - OK
CMP AL,10H ;Больше/равно 0F?
JAE D30 ; да - OK
D20:
MOV BYTE PTR [SI]+3,20H



Ассемблер для IBM PC. Программы. 102


D30:
ADD SI,05 ;Следующий элемент в строке
LEA DI,DISPROW+80
CMP DI,SI
JNE D40
MOV AH,40H ;Функция вывода на экран
MOV BX,01 ;Номер устройства
MOV CX,81 ;Вся строка
LEA DX,DISPROW
INT 21H
LEA SI,DISPROW ;Начальный адрес строки
D40: RET
D10DISP ENDP

Q10CLR PROC NEAR ;Очистка экрана
MOV AX,0600H
MOV BH,03 ;Цвет (07 для ч/б)
MOV CX,0000
MOV DX,184FH
INT 10H
RET
Q10CLR ENDP

CODESG ENDS
END BEGIN































Ассемблер для IBM PC. Программы. 103



page 60,132
TITLE NMSORT (EXE) Ввод и сортировка имен
; -----------------------------------------------
STACK SGMENT PARA STACK 'Stack'
DW 32 DUP(?)
STACK ENDS
; -----------------------------------------------
DATASG SEGMENT PARA 'Data'
NAMEPAR LABEL BYTE ;Имя списка параметров:
MAXNLEN DB 21 ; макс. длина
NAMELEN DB ? ; число введенных символов
NAMEFLD DB 21 DUP(' ') ; имя

CRLF DB 13, 10, '$'
ENDADDR DW ?
MESSG1 DB 'Name?', '$'
NAMECTR DB 00
NAMETAB DB 30 DUP(20 DUP(' ')) ;Таблица имен
NAMESAV DB 20 DUP(?), 13, 10, '$'
SWAPPED DB 00
DATA ENDS
; -----------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATDSG,SS:STACK,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
CLD
LEA DI,NAMETAB
CALL Q10CLR ;Очистить экран
CALL Q20CURS ;Установить курсор
A20LOOP:
CALL B10READ ;Ввести имя с клавиатуры
CMP NAMELEN,00 ;Есть ли еще имена?
JZ A30 ; нет - идти на сортировку
CMP NAMECTR,30 ;Введено 30 имен?
JE A30 ; да - идти на сортировку
CALL D10STOR ;Записать имя в таблицу
JMP A20LOOP
A30: ;Конец ввода имен
CALL Q10CLR ;Очистить экран
CALL Q20CURS ; и установить курсор
CMP NAMECTR,01 ;Введено менее 2 имен?
JBE A40 ; да - выйти
CALL G10SORT ;Сортировать имена
CALL K10DISP ;Вывести результат на экран
A40: RET ;Завершить программу
BEGIN ENDP



Ассемблер для IBM PC. Программы. 104


; Ввод имен с клавиатуры?
; ----------------------
B10READ PROC
MOV AH,09
LEA DX,MESSG1 ;Вывести текст запроса
INT 21H
MOV AH,0AH
LEA DX,NAMEPAR ;Ввести имя
INT 21H
MOV AH,09
LEA DX,CRLF ;Вывести CRLF
INT 21H

MOV BH,00 ;Очистить поле после имени
MOV BL,NAMELEN ;Получить счетчик символов
MOV CX,21
SUB CX,BX ;Вычислить оставшуюся длину
B20:
MOV NAMEFLD[BX],20H ;Установить символ пробела
INC BX
LOOP B20
RET
B10READ ENDP
; Запись имени в таблицу:
; ----------------------
D10STOR PROC
INC NAMECTR ;Число имен в таблице
CLD
LES SI,NAMEFLD
MOV CX,10
REP MOVSV ;Переслать имя в таблицу
RET
D10STOR ENDP
; Сортировка имен в таблице:
; -------------------------
G10SORT PROC
SUB DI,40 ;Установить адреса останова
MOV ENDADDR,DI
G20:
MOV SWAPPED,00 ;Установить начало
LEA SI,NAMETAB ; таблицы
G30:
MOV CX,20 ;Длина сравнения
MOV DI,SI
ADD DI,20 ;Следующее имя для сравнения
MOV AX,DI
MOV BX,SI
REPE CMPSB ;Сравнить имя со следующим
JBE G40 ; нет перестановки
CALL H10XCHG ; перестановка
G40:
MOV SI,AX
CMP SI,ENDADDR ;Конец таблицы?



Ассемблер для IBM PC. Программы. 105


JBE G30 ; нет - продолжить
CMP SWAPPED,00 ;Есть перестановки?
JNZ G20 ; да - продолжить,
RET ; нет - конец сортировки
G10SORT ENDP
; Перестановка элементов таблицы:
; ------------------------------
H10XCHG PROC
MOV CX,10
LEA DI,NAMESAV
MOV SI,BX
REP MOVSW ;Сохранить меньший элемент

MOV CX,10
MOV DI,BX
REP MOVSW ;Переслать больший элемент
; на место меньшего
MOV CX,10
LEA SI,NAMESAV
REP MOVSW ;Переслать сохраненный
; элемент на место большего
MOV SWAPPED,01 ;Признак перестановки
RET
H10XCHG ENDP
; Вывод на экран отсортированные имена:
; ------------------------------------
K10DISP PROC
LEA SI,NAMETAB
K20:
LEA DI,NAMESAV ;Начальный адрес таблицы
MOV CX,10
REP MOVSV
MOV AH,09
LEA DX,NAMESAV
INT 21H ;Вывести на экран
DEC NAMECTR ;Это последний элемент?
JNZ K20 ; нет - повторить цикл,
RET ; да - выйти
K10DISP ENDP
; Очистка экрана:
; --------------
Q10CLR PROC
MOV AX,0600H
MOV BH,61H ;Цвет (07 для ч/б)
SUB CX,CX
MOV DX,184FH
INT 10H
RET
Q10CLR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC
MOV AH,02



Ассемблер для IBM PC. Программы. 106


SUB BH,BH
SUB DX,DX ;Установить курсор в 00,00
INT 10H
RET
Q20CURS ENDP

CODESG ENDS
END BEGIN
















































Ассемблер для IBM PC. Программы. 107



page 60,132
TITLE FCBCREAT (EXE) Использование FCB для создания файла
;----------------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 80 DUP(?)
STACKSG ENDS
;----------------------------------------------------------
DATASG SEGMENT PARA 'Data'
RECLEN EQU 32
NAMEPAR LABEL BYTE ;Список параметров:
MAXLEN DB RECLEN ; макс.длина имени
NAMELEN DB ? ; число введенных символов
NAMEDTA DB RECLEN DUP(' ') ; область передачи (DTA)

FCBREC LABEL BYTE ;FCB для дискового файла
FCBDRIV DB 04 ; дисковод D
FCBNAME DB 'NAMEFILE' ; имя файла
FCBEXT DB 'DAT' ; тип файла
FCBBLK DW 0000 ; номер текущего блока
FCBRCSZ DW ? ; размер логической записи
FCBFLSZ DD ? ; размер файла (DOS)
DW ? ; дата (DOS)
DT ? ; зарезервировано (DOS)
FCBSQRC DB 00 ; номер текущей записи
DD ? ; относительный номер

CRLF DB 13,10,'$'
ERRCDE DB 00
PROMPT DB 'Name? ','$'
ROW DB 01
OPNMSG DB '*** Open error ***', '$'
WRTMSG DB '*** Write error ***', '$'
DATASG ENDS
; ---------------------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
MOV AX,0600H
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL C10OPEN ;Открыть, установить DTA
CMP ERRCDE,00 ;Есть место на диске?
JZ A20LOOP ; да - продолжить,
RET ; нет - вернуться в DOS
A20LOOP:
CALL D10PROC



Ассемблер для IBM PC. Программы. 108


CMP NAMELEN,00 ;Конец ввода?
JNE A20LOOP ; нет - продолжить,
CALL G10CLSE ; да - закрыть файл
RET ; и вернуться в DOS
BEGIN ENDP
; Открытие дискового файла:
; ------------------------
C10OPEN PROC NEAR
MOV AH,16H ;Функция создания файла
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Есть место на диске?
JNZ C20 ; нет - ошибка

MOV FCBRCSZ,RECLEN ;Размер записи (EQU)
LEA DX,NAMEDTA ;Загрузить адрес DTA
MOV AH,1AH
INT 21AH
RET
C20:
LEA DX,OPNMSG ;Сообщение об ошибке
CALL X10ERR
RET
C10OPEN ENDP
; Ввод с клавиатуры:
; -----------------
D10PROC PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,PROMPT ;Выдать запрос
INT 21H

MOV AH,0AH ;Функция ввода
LEA DX,NAMEPAR ;Ввести имя файла
INT 21H
CALL E10DISP ;Прокрутка на экране

CMP NAMELEN,00 ;Имя введено?
JNE D20 ; да - продолжить,
RET ; нет - выйти
D20:
MOV BH,00 ;Заменить символ Return
MOV BL,NAMELEN
MOV NAMEDTA[BX],' ' ;Записать пробел
CALL F10WRIT ;Вызвать
; подпрограмму записи
CLD
LEA DI,NAMEDTA ;Очистить
MOV CX,RECLEN / 2 ; поле
MOV AX,2020H ; имени
REP STOSW
RET ;Выйти
D10PROC ENDP
; Прокрутка и установка курсора:



Ассемблер для IBM PC. Программы. 109


; -----------------------------
E10DISP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,CRLF ;CR/LF
INT 21H ;Вызов DOS
CMP ROW,18 ;Последняя строка экрана?
JAE E20 ; да - обойти,
INC ROW ; нет - увеличить строку
RET
E20:
MOV AX,0601H ;Прокрутка на 1 строку
CALL Q10SCR
CALL Q20CURS ;Установить курсор
RET
E10DISP ENDP
; Запись на диск:
; --------------
F10WRIT PROC NEAR
MOV AH,15H ;Функция записи
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Запись без ошибок?
JZ F20 ; да
LEA DX,WRTMSG ; нет -
CALL X10ERR ; выдать сообщение
MOV NAMELEN,00
F20: RET
F10WRIT ENDP
; Закрытие дискового файла:
; ------------------------
G10CLSE PROC NEAR
MOV NAMEDTA,1AH ;Установить EOF
CALL F10WRIT
MOV AH,10H ;Функция закрытия
LEA DX,FCBREC
INT 21H
RET
G10CLSE ENDP
; Прокрутка экрана:
; ----------------
Q10SCR PROC NEAR ;AX уже установлен
MOV BH,1EH ;Цвет желтый на синем
MOV CX,0000
MOV DX,184FH
INT 10H ;Прокрутка
RET
Q10SCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02
MOV BH,00
MOV DL,00



Ассемблер для IBM PC. Программы. 110


MOV DH,ROW ;Установить курсор
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке на диске:
; ----------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит
INT 21H ; адрес сообщения
MOV ERRCDE,01 ;Установить код ошибки
RET
X10ERR ENDP

CODESG ENDS
END BEGIN









































Ассемблер для IBM PC. Программы. 111



TITLE FCBREAD (EXE) Чтение записей созданных в CREATDSK
; -------------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 80 DUP(?)
STACKSG ENDS
;--------------------------------------------------------
DATASG SEGMENT PARA 'Data'
FCBREC LABEL BYTE ;FCB для файла
FCBDRIV DB 04 ; дисковод D
FCBNAME DB 'NAMEFILE' ; имя файла
FCBEXT DB 'DAT' ; тип файла
FCBBLK DW 0000 ; номер текущего блока
FCBRCSZ DW 0000 ; длина логической записи
DD ? ; размер файла (DOS)
DW ? ; дата (DOS)
DT ? ; зарезервировано (DOS)
FCBSQRC DB 00 ; текущий номер записи
DD ? ; относительный номер

RECLEN EQU 32 ;Длина записи
NAMEFLD DB RECLEN DUP(' '), 13, 10, '$'

ENDCDE DB 00
OPENMSG DB '*** Open error ***', '$'
READMSG DB '*** Read error ***', '$'
ROW DB 00
DATASG ENDS
;--------------------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
MOV AX,0600H
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL E10OPEN ;Открыть файл,
; установить DTA
CMP ENDCDE,00 ;Открытие без ошибок?
JNZ A90 ; нет - завершить
A20LOOP:
CALL F10READ ;Прочитать запись
CMP ENDCDE,00 ;Чтение без ошибок?
JNZ A90 ; нет - выйти
CALL G10DISP ;Выдать имя на экран
JMP A20LOOP ;Продолжить
A90: RET ;Завершить
BEGIN ENDP



Ассемблер для IBM PC. Программы. 112


; Открытие файла на диске:
; -----------------------
E10OPEN PROC NEAR
LEA X,FCBREC
MOV AH,0FH ;Функция открытия
INT 21H
CMP AL,00 ;Файл найден?
JNZ E20 ; нет - ошибка

MOV FCBRCSZ,RECLEN ;Длина записи (EQU)
MOV AH,1AH
LEA DX,NAMEFLD ;Адрес DTA
INT 21H
RET
E20:
MOV ENDCDE,01 ;Сообщение об ошибке
LEA DX,OPENMSG
CALL X10ERROR
RET
E10OPEN ENDP
; Чтение дисковой записи:
; ----------------------
F10READ PROC NEAR
MOV AH,14H ;Функция чтения
LEA DX,FCBREC
INT 21H
CMP NAMEFLD,1AH ;Считан маркер EOF?
JNE F20 ; нет
MOV ENDCDE,01 ; да
JMP F90
F20:
CMP AL,00 ;Чтение без ошибок?
JZ F90 ; да - выйти
MOV ENDCDE,01 ;Нет:
CMP AL,01 ;Конец файла?
JZ F90 ; да - выйти,
LEA DX,READMSG ; нет - значит
CALL X10ERR ; ошибка чтения
F90:
RET
F10READ ENDP
; Вывод записи на экран:
; ---------------------
G10DISP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,NAMEFLD
INT 21H
CMP ROW,20 ;Последняя строка экрана?
JAE G30 ; нет -
INC ROW ; да - увеличить строку
JMP G90
G30:
MOV AX,0601H



Ассемблер для IBM PC. Программы. 113


CALL Q10SCR ; прокрутить
CALL Q20CURS ; установить курсор
G90: RET
G10DISP ENDP
; Прокрутка (скроллинг) экрана:
; ----------------------------
Q10SCR PROC NEAR ;AX уже установлен
MOV BH,1EH ;Установить цвет
MOV CX,0000
MOV DX,184FH ;Функция прокрутки
INT 10H
RET
Q1OSCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02
MOV BH,00
MOV DH,ROW
MOV DL,00
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке на диске:
; ----------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит адрес
INT 21H ; сообщения
RET
X10ERR ENDP

CODESG ENDS
END BEGIN



page 60,132
TITLE RANREAD (COM) Прямое чтение записей,
; созданных в FCBCREAT
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
;-----------------------------------------------------
FCBREC LABEL BYTE ;FCB для дискового файла
FCBDRIV DB 04 ; дисковод D
FCBNAME DB 'MAMEFILE' ; имя файла
FCBEXT DB 'DAT' ; тип файла
FCBBLK DW 0000 ; номер текущего блока
FCBRCSZ DW 0000 ; длина логической записи
DD ? ; размер файла (DOS)
DW ? ; дата (DOS)
DT ? ; зарезервировано (DOS)



Ассемблер для IBM PC. Программы. 114


DB 00 ; номер текущей записи
FCBRNRC DD 000000000 ; относительный номер

RECLEN EQU 32 ;Длина записи
RECDPAR LABEL BYTE ;Список параметров:
MAXLEN DB 3 ;
ACTLEN DB ? ;
RECDNO DB 3 DUP(' ') ;

NAMEFLD DB RECLEN DUP(' '),13,10,'$' ;DTA

OPENMSG DB '*** Open error ***',13,10,'$'
READMSG DB '*** Read error ***',13,10,'$'
COL DB 00
PROMPT DB 'Record number? $'
ROW DB 00
ENDCDE DB 00
;-----------------------------------------------------
MAIN PROC NEAR
CALL Q10CLR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL C10OPEN ;Открыть файл,
; установить DTA
CMP ENDCDE,00 ;Открытие без ошибок?
JZ A20LOOP ; да - продолжить,
RET ; нет - завершить
A20LOOP:
CALL D10RECN ;Получить номер записи
CMP ACTLEN,00 ;Есть запрос?
JE A40 ; нет - выйти
CALL F10READ ;Чтение (прямой доступ)
CMP ENDCDE,00 ;Есть ошибки чтения?
JNZ A30 ; да - обойти
CALL G10DISP ;Вывести на экран
A30:
JMP A20LOOP
A40: RET ;Завершить программу
MAIN ENDP
; Подпрограмма открытия файла на диске:
; ------------------------------------
C10OPEN PROC NEAR
MOV AH,0FH ;Функция открытия
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Открытие нормальное?
JNZ C20 ; нет - ошибка
MOV FCBRCSZ,RECLEN ;Длина записи (EQU)
MOV AH,1AH
LEA DX,NAMEFLD ;Установить адрес DTA
INT 21H
RET
C20:
LEA DX,OPENMSG



Ассемблер для IBM PC. Программы. 115


CALL X10ERR
RET
C10OPEN ENDP
; Ввод с клавиатуры номера записи:
; -------------------------------
D10RECN PROC NEAR
MOV AH,09H ;Функция вывода на экран
LEA DX,PROMPT
INT 21H
MOV AH,0AH ;Функция ввода с клавиатуры
LEA DX,RECDPAR
INT 21H
CMP ACTLEN,01 ;Проверить длину (0,1,2)
JB D40 ;Длина 0, завершить
JA D20
SUB AH,AH ;Длина 1
MOV AL,RECDNO
JMP D30
D20:
MOV AH,RECDNO ;Длина 2
MOV AL,RECDNO+1
D30:
AND AX,0F0FH ;Удалить ASCII тройки
AAD Преобразовать в двоичное
MOV WORD PTR FCBRNRC,AX
D40:
MOV COL,20
CALL Q20CURS ;Установить курсор
RET
D10RECN ENDP
; Чтение дисковой записи:
; ----------------------
F10READ PROC NEAR
MOV ENDCDE,00 ;Очистить код завершения
MOV AH,21H ;Функция прямого чтения
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Чтение без ошибок?
JZ F20 ; да - выйти
LEA DX,READMSG ; нет - выдать
CALL X10ERR ; сообщение об ошибке
F20: RET
F10READ ENDP
; Вывод имени на экран:
; --------------------
G10DISP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,NAMEFLD
INC 21H
INC ROW
MOV COL,00
RET
G10DISP ENDP



Ассемблер для IBM PC. Программы. 116


; Очистка экрана:
; --------------
Q10CLR PROC NEAR
MOV AX,0600H ;Функция прокрутки
MOV BH,41H ;Цвет (07 для ч/б)
MOV CX,0000
MOV DX,184FH
INT 10H
RET
Q10CLR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02 ;Функция установки
MOV BH,00 ; курсора
MOV DH,ROW
MOV DL,COL
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке на диске:
; ----------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит адрес
INT 21H ; сообщения
INC ROW
MOV ENDCDE,01
RET
X10ERR ENDP
CODESG ENDS
END BEGIN

























Ассемблер для IBM PC. Программы. 117



TITLE RANBLOK (COM) Прямое блочное чтение файла
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
;----------------------------------------------------
FCBREC LABEL BYTE ;FCB для дискового файла
FCBDRIV DB 04 ; дисковод D
FCBNAME DB 'NAMEFILE' ; имя файла
FCBEXT DB 'DAT' ; тип файла
FCBBLK DW 0000 ; номер текущего блока
FCBRCSZ DW 0000 ; логическая длина записи
FCBFLZ DD ? ; DOS размер файла
DW ? ; DOS дата
DT ? ; DOS зарезервировано
DB 00 ; номер текущей записи
FCBRNRC DD 00000000 ; относительный номер

DSKRECS DB 1024 DUP(?),'$' ;DTA для блока записей

ENDCODE DB 00
NORECS DW 25 ;Число записей
OPENMSG DB '*** Open error ***',13,10,'$'
READMSG DB '*** Open error ***',13,10,'$'
ROWCTR DB 00
; ---------------------------------------------------
MAIN PROC NEAR
CALL Q10CLR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL E10OPEN ;Открыть файл,
; установить DTA
CMP ENDCODE,00 ;Успешное открытие?
JNZ A30 ; нет - выйти
CALL F10READ ;Читать записи
CALL G10DISP ;Вывод блока на экран
A30: RET ;Завершить программу
MAIN ENDP
; Открыть дисковый файл:
; ---------------------
E10OPEN PROC NEAR
MOV AH,0FH ;Функция открытия файла
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Успешное открытие?
JNZ A30 ; нет - ошибка

MOV FCBRCSZ,0020H ;Размер записи
MOV AH,1AH
LEA DX,DSKRECS ;Установить адрес DTA
INT 21H
RET
E20:



Ассемблер для IBM PC. Программы. 118


LEA DX,OPENMSG ;Ошибка открытия файла
CALL X10ERR
RET
E10OPEN ENDP
; Чтение блока:
; ------------
F10READ PROC NEAR
MOV AH,27H ;Прямое чтение блока
MOV CX,NORECS ;Число записей
LEA DX,FCBREC
INT 21H
MOV ENDCODE,AL ;Сохранить код возврата
RET
F10READ ENDP
; Вывод блока на экран:
; --------------------
G10DISP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,DSKRECS
INT 21H
RET
G10DISP ENDP
; Подпрограмма очистки экрана:
Q10CLR PROC NEAR
MOV AX,0600H ;Функция скрол
MOV BH,41H ;Цвет (07 для ч/б)
MOV CX,0000
MOV DX,184FH
INT 10H
RET
Q10CLR ENDP
; Подпрограмма установки курсора:
; ------------------------------
Q20CURS PROC NEAR
MOV AH,02 ;Функция установки курсора
MOV BH,00
MOV DH,ROWCTR
MOV DL,00
INT 10H
INC ROWCTR
RET
Q20CURS ENDP
; Подпрограмма сообщения об ошибке диска:
; --------------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит адрес
INT 21H ; сообщения
MOV ENDCODE,01
RET
X10ERR ENDP

CODESG ENDS
END BEGIN



Ассемблер для IBM PC. Программы. 119



TITLE SELDEL (COM) Выборочное удаление файлов
; Предполагается текущий дисковод;
; Примеры параметров: *.*, *.BAK, и т.д.
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN JMP MAIN
; ----------------------------------------------------------
TAB EQU 09
LF EQU 10
CR EQU 13
CRLF DB CR,LF,'$'
DELMSG DB TAB,'Erase','$'
ENDMSG DB CR,LF,'No more directory entries',CR,LF,'$'
ERRMSG DB 'Write protected disk','$'
PROMPT DB 'y = Erase, N = Keep, Ret = Exit',CR,LF,'$'
; ----------------------------------------------------------
MAIN PROC NEAR ;Главная процедура
MOV AH,11H ;Найти первый элемент
CALL D10DISK
CMP AL,0FFH ;Если нет элементов,
JE A90 ; то выйти
LEA DX,PROMPT ;Текст запроса
CALL B10DISP
A20:
LEA DX,DELMSG ;Выдать сообщение
CALL B10DISP ; об удалении файла
MOV CX,11 ;11 символов
MOV SI,81H ;Начало имени файла
A30:
MOV DL,[SI] ;Текущий символ
CALL C10CHAR ; для вывода на экран
INC SI ;Следующий символ
LOOP A30
MOV DL,'?'
CALL C10CHAR
MOV AH,01 ;Получить односимвольный
INT 21H ; ответ
CMP AL,ODH ;Символ Return?
JE A90 ; да - выйти
OR AL,00100000B ;Перекодировать
; в прописную букву
CMP AL,'y' ;Запрошено удаление?
JNE A50 ; нет - обойти,
MOV AH,13H ; да - удалить файл
MOV DX,80H
INT 21H
CMP AL,0 ;Успешное удаление?
JZ A50 ; да - обойти
LEA DX,ERRMSG ; нет - выдать
CALL B10DISP ; предупреждение
JMP A90



Ассемблер для IBM PC. Программы. 120


A50:
LEA DX,CRLF ;Перевести строку на экране
CALL B10DISP
MOV AH,12H
CALL B10DISK ;Получить следующий элемент
CMP AL,0FFH ;Есть еще?
JNE A20 ; да - повторить
A90:
RET ;Выход в DOS
MAIN ENDP
; Вывод строки на экран;
; ---------------------
B10DISP PROC NEAR ;в DX находится адрес
MOV AH,09 ; строки
INT 21H
RET
B10DISP ENDP
; Вывод символа на экран;
; ----------------------
C10CHAR PROC NEAR ;в DL находится символ
MOV AH,02
INT 21H
RET
C10CHAR ENDP
; Чтение элемента каталога:
; ------------------------
D10DISK PROC NEAR
MOV DX,5CH ;Установить FCB
INT 21H
CMP AL,0FFH ;Есть еще элементы?
JNE D90
PUSH AX ;Сохранить AL
LEA DX,ENDMSG
CALL B10DISP
POP AX ;Восстановить AL
D90: RET
D10DISK ENDP

CODESG ENDS
END BEGIN
















Ассемблер для IBM PC. Программы. 121



page 60,132
TTILE HANCREAT (EXE) Создание файла на диске
; -----------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 80 DUP(?)
STACKSG ENDS
; -----------------------------------------------------
DATASG SEGMENT PARA 'Data'
NAMEPAR LABEL BYTE ;Список параметров:
MAXLEN DB 30 ;
NAMELEN DB ? ;
NAMEREC DB 30 DUP(' '), 0DH, 0AH ; введенное имя,
; CR/LF для записи
ERRCDE DB 00
HANDLE DW ?
PATHNAM DB 'D:\NAMEFILE.DAT',0
PROMPT DB 'Name? '
ROW DB 01
OPNMSG DB '*** Open error ***', 0DH, 0AH
WRTMSG DB '*** Write error ***', 0DH, 0AH
DATASG ENDS
; -------------------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
MOV AX,0600H
CALL Q10SCR ;Очистка экрана
CALL Q20CURS ;Установка курсора
CALL C10CREA ;Создание файла,
; установка DTA
CMP ERRCDE,00 ;Ошибка при создании?
JZ A20LOOP ; да - продолжить,
RET ; нет - вернуться в DOS
A20LOOP:
CALL D10PROC
CMP NAMELEN,00 ;Конец ввода?
JNE A20LOOP ; нет - продолжить,
CALL G10CLSE ; да - закрыть файл
RET ; и выйти в DOS
BEGIN ENDP
; Создание файла на диске:
; -----------------------
C10CREA PROC NEAR
MOV AH,3CH ;Функция создания файла
MOV CX,00 ;Нормальный атрибут
LEA CX,PATHNAM



Ассемблер для IBM PC. Программы. 122


INT 21H
JC C20 ;Есть ошибка?
MOV HANDLE,AX ; нет - запомнить номер,
RET
C20: ; да -
LEA DX,OPNMSG ; выдать сообщение
CALL X10ERR ; об ошибке
RET
C10CREA ENDP
; Ввод с клавиатуры:
; -----------------
D10PROC PROC NEAR
MOV AH,40H ;Функция вывода на экран
MOV BX,01 ;Номер (Handle)
MOV CX,06 ;Длина текста запроса
LEA DX,PROMPT ;Выдать запрос
INT 21H

MOV AH,0AH ;Функция ввода с клавиатуры
LEA DX,NAMEPAR ;Список параметров
INT 21H
CMP NAMELEN,00 ;Имя введено?
JNE D20 ; да - обойти
RET ; нет - выйти
D20:
MOV AL,20H ;Пробел для заполнения
SUB CH,CH
MOV CL,NAMELEN ;Длина
LEA DI,NAMEREC ;
ADD DI,CX ;Адрес + длина
NEG CX ;Вычислить
ADD CX,30 ; оставшуюся длину
REP STOSB ;Заполнить пробелом
D90:
CALL F10WRIT ;Запись на диск
CALL E10SCRL ;Проверка на скролинг
RET
D10PROC ENDP
; Проверка на скролинг:
; --------------------
E10SCRL PROC NEAR
CMP ROW,18 ;Последняя строка экрана
JAE E10 ; да - обойти,
INC ROW ; нет - увеличить строку
JMP E10
E10:
MOV AX,0601H ;Продвинуть на одну строку
CALL Q10SCR
E90: CALL Q20CURS ;Установка курсора
RET
E10SCRL ENDP
; Запись на диск:
; --------------



Ассемблер для IBM PC. Программы. 123


F10WRIT PROC NEAR
MOV AH,40H ;Функция записи на диск
MOV BX,HANDLE
MOV CX,32 ;30 для имени + 2 для CR/LF
LEA DX,NAMEREC
INT 21H
JNC F20 ;Ошибка записи?
LEA DX,WRTMSG ; да -
CALL X10ERR ; выдать предупреждение
MOV NAMELEN,00
F20:
RET
F10WRIT ENDP
; Закрытие файла на диске:
; -----------------------
G10CLSE PROC NEAR
MOV NAMEREC,1AH ;Маркер конца записи (EOF)
CALL F10WRIT
MOV AH,3EH ;Функция закрытия
MOV BX,HANDLE
INT 21H
RET
G10CLSE ENDP
; Прокрутка (скроллинг) экрана:
; ----------------------------
Q10SCR PROC NEAR ;в AX - адрес элемента
MOV BH,1EH ;Цвет - желтый на синем
MOV CX,0000
MOV DX,184FH
INT 10H ;Скроллинг
RET
Q10SCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02
MOV BH,00
MOV DH,ROW ;Установить курсор
MOV DL,00
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке:
; -------------------------
X10ERR PROC NEAR ;DX содержит
MOV AH,40H ; адрес сообщения
MOV BX,01
MOV CX,21 ;Длина сообщения
INT 21H
MOV ERRCDE,01 ;Установить код ошибки
RET
X10ERR ENDP




Ассемблер для IBM PC. Программы. 124


CODESG ENDS
END BEGIN






















































Ассемблер для IBM PC. Программы. 125



page 60,132
TITLE HANREAD (EXE) Чтение записей, созданных в HANCREAT
; -----------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 80 DUP(?)
STACKSG ENDS
; -----------------------------------------------------
DATASG SEGMENT PARA 'Data'
ENDCDE DB 00
HANDLE DW ?
IOAREA DB 32 DUP(' ')
PATHNAM DB 'D:\NAMEFILE.SRT',0
OPENMSG DB '*** Open error ***', 0DH, 0AH
READMSG DB '*** Read error ***', 0DH, 0AH
ROW DB 00
DATASG ENDS
; ------------------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
MOV AX,0600H
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL E100PEN ;Открыть файл,
; ; установить DTA
CMP ENDCDE,00 ;Ошибка открытия?
JNZ A90 ; да - завершить программу
A20LOOP:
CALL F10READ ;Чтение записи с диска
CMP ENDCDE,00 ;Ошибка чтения?
JNZ A90 ; да - выйти,
CALL G10DISP ; нет - выдать имя,
JMP A20LOOP ; и продолжить
A90: RET
BEGIN ENDP
; Открытие файла:
; --------------
E100PEN PROC NEAR
MOV AH,3DH ;Функция открытия
MOV CX,00 ;Нормальные атрибуты
LEA DX,PATHNAM
INT 21H
JC E20 ;Ошибка открытия?
MOV HANDLE,AX ; нет - сохранить
RET ; файловый номер
E20:



Ассемблер для IBM PC. Программы. 126


MOV ENDCDE,01 ; да - выдать
LEA DX,OPENMSG ; сообщение об ошибке
CALL X10ERR
RET
E100PEN ENDP
; Чтение дисковой записи:
; ----------------------
F10READ PROC NEAR
MOV AX,3FH ;Функция чтения
MOV BX,HANDLE
MOV CX,32 ;30 для имени, 2 для CR/LF
LEA DX,IOAREA
INT 21H
JC F20 ;Ошибка при чтении?
CMP AX,00 ;Конец файла?
JE F30
CMP IOAREA,1AH ;Маркер конца файла (EOF)?
JE F30 ; да - выйти
RET
F20:
LEA DX,READMSG ; нет - выдать
CALL X10ERR ; сообщение об ошибке
F30:
MOV ENDCDE,01 ;Код завершения
F90: RET
F10READ ENDP
; Вывод имени на экран:
; --------------------
G10DISP PROC NEAR
MOV AH,40H ;Функция вывода на экран
MOV BX,01 ;Установить номер
MOV CX,32 ; и длину
LEA DX,IOAREA
INT 21H
CMP ROW,20 ;Последняя строка экрана?
JEA G90 ; да - обойти
INC ROW
RET
G90:
MOV AX,0601H
CALL Q10SCR ;Прокрутка (скроллинг)
CALL

Страницы

Подякувати Помилка?

Дочати пiзнiше / подiлитися