CALL F10XMUL ;Вызвать 2-е умножение
RET
MAIN ENDP
; Умножение двойного слова на слово:
; -----------------------------------------------
E10XMUL PROC
MOV AX,MULTCND+2 ;Умножить правое слова
MUL MULTPLR ; множимого
MOV PRODUCT+4,AX ;Записать произведение
MOV PRODUCT+2,DX

MOV AX,MULTCND ;Умножить левое слово
MUL MULTPLR ; множимого
ADD PRODUCT+2,AX ;Сложить с полученным ранее
ADC PRODUCT,DX
RET
E10XMUL ENDP
; Перемножение двух двойных слов:
; --------------------------------------------
F10XMUL PROC
MOV AX,MULTCND+2 ;Слово-2 множимого
MUL MULTPLR+2 ; * слово-2 множителя
MOV PRODUCT+6,AX ;Сохранить результат
MOV PRODUCT+4,DX

MOV AX,MULTCND+2 ;Слово-2 множимого
MUL MULTPLR ; * слово-1 множителя
ADD PRODUCT+4,AX ;Сложить с предыдущим
ADC PRODUCT+6,DX
ADC PRODUCT,00 ;Прибавить перенос

MOV AX,MULTCND ;Слово-1 множимого
MUL MULTPLR+2 ; * слово-2 множителя
ADD PRODUCT+4,AX ;Сложить с предыдущим



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


ADC PRODUCT+6,DX
ADC PRODUCT,00 ;Прибавить перенос
MOV AX,MULTCND ;Слово-1 множимого
MUL MULTPLR ; * слово-1 множителя
ADD PRODUCT+2,AX ;Сложить с предыдущим
ADC PRODUCT,DX
RET
F10XMUL ENDP
; Очистка области результата:
; ----------------------------------------
Z10XMUL PROC
MOV PRODUCT,0000
MOV PRODUCT+2,0000
MOV PRODUCT+4,0000
MOV PRODUCT+6,0000
RET
Z10XMUL ENDP

CODESG ENDS
END BEGIN




































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



page 60,132
TITLE EXDIV (COM) Пример операций DIV и IDIV
CODESG SEGMENT PARA 'Code'
ORG 100H
BEGIN: JMP SHORT MAIN
; ---------------------------------------------
BYTE1 DB 80H ;Data items
BYTE2 DB 16H
WORD1 DW 2000H
WORD2 DW 0010H
WORD3 DW 1000H
; ---------------------------------------------
MAIN PROC NEAR ;Основная процедура
CALL D10DIV ;Вызов подпрограммы DIV
CALL E10IDIV ;Вызов подпрограммы IDIV
MAIN ENDP
; Примеры с командой DIV:
; ---------------------------------------------
D10DIV PROC
MOV AX,WORD1 ;Слово / байт
DIV BYTE1 ; остаток:частное в AH:AL
MOV AL,BYTE1 ;Байт / байт
SUB AH,AH ; расширить делимое в AH
DIV BYTE3 ; остаток:частное в AH:AL

MOV DX,WORD2 ;Двойное слово / слово
MOV AX,WORD3 ; делимое в DX:AX
DIV WORD1 ; остаток:частное в DX:AX
MOV AX,WORD1 ;Слово / слово
SUB DX,DX ; расширить делимое в DX
DIV WORD3 ; остаток:частное в DX:AX
RET
D10DIV ENDP
; Примеры с командой IDIV:
; ---------------------------------------------
E10IDIV PROC
MOV AX,WORD1 ;Слово / байт
IDIV BYTE1 ; остаток:частное в AH:AL
MOV AL,BYTE1 ;Байт / байт
CBW ; расширить делимое в AH
IDIV BYTE3 ; остаток:частное в AH:AL

MOV DX,WORD2 ;Двойное слово / слово
MOV AX,WORD3 ; делимое в DX:AX
IDIV WORD1 ; остаток:частное в DX:AX
MOV AX,WORD1 ;Слово / слово
CWD ; расширить делимое в DX
IDIV WORD3 ; остаток:частное в DX:AX
RET
E10DIV ENDP

CODESG ENDS



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


END BEGIN



TITLE ASCADD (COM) Сложение чисел в ASCII-формате
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; -----------------------------------------------
ASC1 DB '578' ;Элементы данных
ASC2 DB '694'
ASC3 DB '0000'
; -----------------------------------------------
MAIN PROC NEAR
CLC
LEA SI,AASC1+2 ;Адреса ASCII-чисел
LEA DI,AASC2+2
LEA BX,AASC1+3
MOV CX,03 ;Выполнить 3 цикла
A20:
MOV AH,00 ;Очистить регистр AH
MOV AL,[SI] ;Загрузить ASCII-байт
ADC AL,[DI] ;Сложение (с переносом)
AAA ;Коррекция для ASCII
MOV [BX],AL ;Сохранение суммы
DEC SI
DEC DI
DEC BX
LOOP A20 ;Циклиться 3 раза
MOV [BX],AH ;Сохранить перенос
RET
MAIN ENDP
CODESG ENDS
END BEGIN





















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



TITLE ASCMUL (COM) Умножение ASCII-чисел
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP MAIN
; ---------------------------------------------
MULTCND DB '3783' ;Элементы данных
MULTPLR DB '5'
PRODUCT DB 5 DUP(0)
; ---------------------------------------------
MAIN PROC NEAR
MOV CX,04 ;4 цикла
LEA SI,MULTCND+3
LEA DI,PRODUCT+4
AND MULTPLR,0FH ;Удалить ASCII-тройку
A20:
MOV AL,[SI] ;Загрузить ASCII-символ
; (можно LODSB)
AND AL,OFH ;Удалить ASCII-тройку
MUL MULTPLR ;Умножить
AAM ;Коррекция для ASCII
ADD AL,[DI] ;Сложить с
AAA ; записанным
MOV [DI],AL ; произведением
DEC DI
MOV [DI],AH ;Записать перенос
DEC SI
LOOP A20 ;Циклиться 4 раза
RET
MAIN ENDP
CODESG ENDS
END BEGIN



TITLE ASCDIV (COM) Деление ASCII-чисел
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; ---------------------------------------------
DIVDND DB '3698' ;Элементы данных
DIVSOR DB '4'
QUOTNT DB 4 DUP(0)
; ---------------------------------------------
MAIN PROC NEAR
MOV CX,04 ;4 цикла
SUB AH,AH ;Стереть левый байт делимого
AND DIVSOR,0FH ;Стереть ASCII 3 в делителе
LEA SI,DIVDND
LEA DI,QUOTNT
A20:



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


MOV AL,[SI] ;Загрузить ASCII байт
; (можно LODSB)
AND AL,0FH ;Стереть ASCII тройку
AAD ;Коррекция для деления
DIV DIVSOR ;Деление
MOV [DI],AL ;Сохранить частное
INC SI
INC DI
LOOP A20 ;Циклиться 4 раза
RET
MAIN ENDP
CODEGS ENDS
END BEGIN











































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



TITLE SCREMP (EXE) Ввод времени и расценки,
;вывод величины оплаты
; ----------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 32 DUP(?)
STACKSG ENDS
; ----------------------------------------------------
DATASG SEGMENT PARA 'Data'
HRSPAR LABLE BYTE ;Список параметров для
; ввода времени:
MAXHLEN DB 6 ;---------------------
ACTHLEN DB ?
HRSFLD DB 6 DUP(?)

RATEPAR LABLE BYTE ;Список параметров для
; ввода расценки:
MAXRLEN DB 6 ;---------------------
ACTRLEN DB ?
RATEFLN DB 6 DUP(?)

MESSG1 DB 'Hours worked? ','$'
MESSG2 DB 'Rate of pay? ','$'
MESSG3 DB 'Wage = '
ASCWAGE DB 10 DUP(30H), 13, 10, '$'
ADJUST DW ?
ASCHRS DB 0
ASCRATE DB 0
BINVAL DW 00
BINHRS DW 00
BINRATE DW 00
COL DB 00
DECIND DB 00
MULT10 DW 01
NODEC DW 00
ROW DB 00
SHIFT DW ?
TENWD DW 10
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 ;Установить курсор
A20LOOP:



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


CALL B10INPT ;Ввести время и расценку
CMP ACTHLEN,00 ;Завершить работу?
JE A30
CALL D10HOUR ;Получить двоичное время
CALL E10RATE ;Получить двоичную расценку
CALL F10MULT ;Расчитать оплату
CALL G10WAGE ;Преобразовать в ASCII
CALL K10DISP ;Выдать результат на экран
JMP A20LOOP
A30:
MOV AX,0600H
CALL Q10SCR ;Очистить экран
RET ;Выйти из программы
BEGIN ENDP
; Ввод времени и расценки
; ----------------------------------------------------
B10INPT PROC
LEA DX,MESSG1 ;Запрос для ввода времени
MOV AH,09
INT 21H
LEA DX,HRSPAR ;Ввести время
MOV AH,0AH
INT 21H
CMP ACTHLEN,00 ;Пустой ввод?
JNE B20
RET ; да - вернуться A20LOOP
B20:
MOV COL,25 ;Установить столбец
CALL Q20CURS
LEA DX,MESSG2 ;Запрос для ввода засценки
MOV AH,09
INT 21H
LEA DX,RATEPAR ;Ввести расценку
MOV AH,0AH
INT 21H
RET
B10INPT ENDP
; Обработка времени:
; -----------------
D10HOUR PROC
MOV NODEC,00
MOV CL,ACTHLEN
SUB CH,CH
LEA SI,HRSFLD-1 ;Установить правую позицию
ADD SI,CX ; времени
CALL M10ASBI ;Преобразовать в двоичное
MOV AX,BINVAL
MOV BINHRS,AX
RET
D10HOUR ENDP
; Обработка расценки:
; ------------------
E10RATE PROC



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


MOV CL,ACTRLEN
SUB CH,CH
LEA SI,RATEFLD-1 ;Установить правую позицию
ADD SI.CX ; расценки
CALL M10ASBI ;Преобразовать в двоичное
MOV AX,BINVAL
MOV BINRATE,AX
RET
E10RATE ENDP
; Умножение, округление и сдвиг:
; -----------------------------
F10MULT PROC
MOV CX,05
LEA DI,ASCWAGE ;Установить формат оплаты
MOV AX,3030H ; в код ASCII (30)
CLD
REP STOSW
MOV SHIFT,10
MOV ADJUST,00
MOV CX,NODEC
CMP CL,06 ;Если более 6 десятичных
JA F40 ; знаков, то ошибка
DEC CX
DEC CX
JLE F30 ;Обойти, если менее 3 знаков
MOV NODEC,02
MOV AX,01
F20:
MUL TENWD ;Вычислить фактор сдвига
LOOP F20
MOV SHIFT,AX
SHR AX,1 ;Округлить результат
MOV ADJUST,AX
F30:
MOV AX,BINHRS
MUL BINRATE ;Вычислить оплату
ADD AX,ADJUST ;Округлить оплату
ADC DX,00
CMP DX,SHIFT ;Результат слишком велик
JB F50 ; для команды DIV?
F40:
SUB AX,AX
JMP F70
F50:
CMP ADJUST,00 ;Сдвиг нее требуется?
JZ F80
DIV SHIFT ;Сдвинуть оплату
F70: SUB DX,DX ;Стереть остаток
F80: RET
F10MULT ENDP
; Преобразование в ASCII формат:
; -----------------------------
G10WAGE PROC



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


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 ;Прочитать запись