Анализ программы Assembler
Задание
Знаковое деление
четырёхсловного делимого на однословный делитель на основе использования
штатной команды процессора div src (формат 64:16=64).
Структурное описание
программы
На входе программы получаем десятичное число -
делимое и делитель. Нам необходимо произвести с их помощью деление. Мы
преобразуем и делимое и делитель в двоичную систему исчисления в ASCII строку,
после преобразования производим деление делимого на делитель. Мы учитываем
остаток от деления и сам результат. После этого преобразуем результат и остаток
в десятичную систему счисления, после чего выводим результат на экран
Описание собственных векторов обработчиков
прерываний
Обработчик мультиплексного прерывания New_2Fh
Прерывание New_2Fh
используется для межпрограммных связей. Поэтому в нашем программном комплексе
используем его для реализации механизма общения между резидентом и транзитной
программой. Для использования в программном комплексе выбрана функция 0С8h,
поскольку ее номер является свободным и предназначена для реализации функции
прикладными программами. Опишем подфункции нашей функции, номер подфункции
задается в регистре al.
Процедура Init: служит для индикации нахождения
резидента в памяти, в результате ее работы al становится равным 0ffh в качестве
основного признака и dx становится равным 8888h
Ппроцедура no также служит для индикации
резидента и выполняет вывод сообщения от резидента на экран.
Процедура uninstall выполняет удаление резидента
из памяти. При помощи функции 25h int 21h восстанавливает старое значение векторов
обработчиков прерываний. И удаляет блок резидента из памяти.
Подфункция 04h выполняет загрузку результа
деления из резидента в транзитную программу. При этом результат содержится в
dx:ax, в случае если процедура умножения не была вызвана значение регистра cx
равно 0ffffh
Обработчик прерывания клавиатуры New_09h
Рис.
программа assembler вектор
В случае если установлен флаг активности
сканирования клавиатуры, выполняет проверку на нажатие Alt+A, если нажата эта
клавиатурная комбинация, то вызывается процедура деления, устанавливается флаг
выполнения деления и снимается флаг активности сканирования клавиатуры.
Div64:
Функция-вычислитель, реализует операцию деления знаковых чисел в формате 64:16.
В виду алгоритмической сложности непосредственной реализации деления чисел в
дополнительном коде эту операцию выполняют как деление с предварительным
преобразованием делимого и делителя в модульную форму с нулевым знаковым
разрядом. Деление проводится в четыре этапа.
Результаты демонстрации программы.
Результат работы
резидента
Рис.
Результаты работы программы
Листинг программы.
Resid.asm
p286n
CSEG
segment
assume
cs:CSEG,
ds:CSEG,
es:CSEG,
ss:CSEG
;настроим сегменты для COM
программы
org 100h
Start:
Переходим на метку инициализации.
jmp
Init
Обработчик мультиплексного прерывания int
2Fh
new_2fh
proc
cmp
ah, 0C8h
;наша функция
jne
no
cmp
al, 00h
;подфункция проверки наличия резидента в памяти
je
testt
cmp
al, 01h
; подфункция визуальной проверки
je
mestest
cmp
al, 02h
;подфункция загрузки данных в поля резидента
je
load
cmp
al, 03h
;подфункция удаления резидента из памяти
je
uninstall
cmp
al, 04h
;подфункция получения результата процедуры
je getno:csdsah, 09hdx, offset mes1
;сообщение21h dx,
[dword ptr
cs:old_09h]
;установка старого вектора 09h
mov
ax, 2509h
int 21h
lds
dx, [dword
ptr cs:old_2fh]
;установка старого вектора 2Fh
mov
ax, 252fh
int 21h
push
cs ;настройка es
на сs
pop
es
mov
ah, 49h
;освобождение сегмента
int 21h
iret
NO:
jmp [dword
ptr cs:old_2fh]
;в старый обработчик без возврата
iret
load: ;загрузка
данных
;ds-si
-семгент оффсет операнда из транцитной программы
push es csesdi, offset operandcx,
5movsw[cs:Active], 0[cs:fl_active], 1[cs:error],0
es
iret
get: ;возврат
результат
push ds csdssi, offset Result
cx, 5
rep
movsw
cmp [Active],
1 ;установка идентификатора вызова процедуры умножения
je
tiret
net:
stc
mov
ch, 0ffh
;сх=0ffffh индикатор
не вызова процедуры
iret
testt: ;проверка
на налицие в памяти
mov al, 0ffhdx, 8888h
mestest:
;проверка с выводом сообщения
push ax dx ds csdsah, 09hdx, offset
mes21hds dx ax
old_2fh
dd ? ;cтарые
адреса векторов прерываний
old_09h
dd ?
;Строка, которая будет выводится
Mes
db 'Резидент в
памяти!',13,10,'$'
Mes1 db
'Резидент выгружен!',13,10,'$'
Mes2 db
'Резидент установлен!',13,10,'$'
new_2fh
endp
;конец обработчика
Operand
DQ 0
Deler Dw 0DQ 0DW 0DB 0 DB 0DB 0 ;флаг
активации
резидента
fl_active
db 0 ;флаг активности
клавиатуры
Error
db 0
buf
dd ?
Neg64 proc
;cмена знака 64
разрядного числа
;bx-
адрес числа
;перевод по схеме !A+1
push ds csds[word ptr bx+6][word ptr
bx+4][word ptr bx+2][word ptr bx][word ptr bx],1[word ptr bx+2],0[word ptr
bx+4],0[word ptr bx+6],0ds
Neg64 endp
---------
Div64 proc
;деление 64 разрядного числа
cmp
bx, 0 ;если нулевой
делитель
jne
ggood
mov [cs:Error],1 ;то ошибка:ds
csds[SignR],1[SignC],1bx,bx ;знак делителяpositive1[SignR] ;учитываем если
-bx:si, [word ptr Operand+6] ;знак делимого
si,si
jns
positive2 ;учитываем если
минус
neg [SignR][SignC]bxbx, offset
OperandNeg64bx:dx, dx ;делениеax, [word ptr Operand+6]bx[word ptr result+6],
axax, [word ptr Operand+4]bx[word ptr result+4], axax, [word ptr
Operand+2]bx[word ptr result+2], axax, [word ptr Operand]bx[word ptr result],
ax
[Rem], dx
cmp [word
ptr result+6],
8000h ;если получили
дольше максимального полодительного
jne welldon[word ptr result+4],
0000hwelldon[word ptr result+2], 0000hwelldon[word ptr result],
0000hwelldon[cs:error], 1 ;то ошибка:[SignC], 1ok1[Rem] ;востановим верные
знаки:[SignC],1ok2bx, offset operandNeg64:ds64 endp
new_09h proc
;Новый обработчик прерывания 09h
pusha ;Сохраним
регистры
push
ds es
mov ax,csds,ax ;ds=cs
[fl_active],1 ;Производить
проверку кодов нажатия клавиш?
je @@work ;Да@@Exit ;Нет
@@work: ;Отфильтровываем
комбинацию Alt-A
in
al,60h ;Читаем
из порта данных клавиатуры скан-код клавиши
cmp
al,1Eh ;Если
это [А], то работаем дальше
jz @@ok
@@Exit:es ds
popa
jmp
dword ptr
cs:[old_09h] ;в
старый обработчик без возврата
@@ok:
mov
ax,40h
mov
es,ax
mov
al,[es:17h] ;Получим
первый байт флагов состояния клавиатуры
test
al,08h ;Клавиша
Alt нажата?
je @@Exit ;Нет,
перейдём в системный обработчик
sti ;Разрешим
аппаратные прерывания
mov [fl_active],0 ;Запретим
дальнейшую проверку нажатия клавиш
mov [active],1bx, [cs:Deler]
DIV64 ;Вызов
процедуры деления при ds=cs
и es=40h
cli ;Запретим
аппаратные прерывания
in
al,61h
;Разрешим дальнейшую работу контроллеру клавиатуры
or al,80h61h,alal,7fh61h,al
al,20h ;Пошлём
в контроллер команду EOI
out 20h,al
pop
es ds
;Восстановим регистры и выйдем из прерывания
popa_09h endp:
ax,0c800h
;проверка на наличие в памяти
int 2fhal, 0ffhinstalldx,
8888hinstallax, [cs:82h]
cmp ax , 'u/'deinstall
mov ah, 9dx, offset message
21h
jne
exit
проверка на off
deinstall:ax, 0c803h2fhexit:ah,
09hdx, offset Mes221h ah,35h ;AH
содержит номер функции (это понятно)
mov
al,09h ;AL
указывает номер прерывания, адрес (или вектор)
;которого нужно получить
int 21h;Теперь
в ES:BX
адрес (вектор) прерывания
(ES
- сегмент, BX - смещение)
mov [word
ptr cs:old_09h],bx
mov
dx,offset
new_09h
;DX должен указывать
на наш обработчик
int 21h
mov
ah,35h ;AH
содержит номер функции (это понятно)
mov
al,2fh ;AL
указывает номер прерывания, адрес (или вектор)
;которого нужно получить
int 21h;Теперь
в ES:BX
адрес (вектор) прерывания
;(ES
- сегмент, BX - смещение)
mov [word
ptr cs:old_2fh],bx
mov [word ptr cs:old_2fh+2],es
ax,252fh
mov
dx,offset
new_2fh ;DX
должен указывать на наш
;обработчик21hdx,offset Init27h:ax,
4c00h
21h
message
db 'Копия резидента
уже присутствует в памяти.',13,10,'Pапустите
с опцией /u для
выгрузки',13,10,'$'
CSEG endsStart.asmn
%TITLE
"HELLO.ASM"small256window N,attrib,y1,x1,y2,x2 ; инициализация (N=0)
или прокрутка окна вверхah,06hal,Nbh,attribch,y1cl,x1dh,y2dl,x210hwindow
readkey ; ожидание ввода
любого символа
mov
ah,10h
; функция ввода символа с ожиданием
int 16h
Endm
readkey
Macro
getmode ; получение режима
дисплея
mov
ah,0Fh
int 10h
mov [oldmode],al
; запись исходного режима дисплея в переменную oldmode
Endm
getmode
Macro
setmode mode
; установка дисплея в режим mode
mov ah,00hal,mode10hsetmodeout_str
mes,leng,attrib ; т√тюф ёююс∙хэш фышэющ leng яю
; рфЁхёє es:offset mes ё рЄЁшсєЄюь
ёшьтюыют attribah,13hal,1bh,0bl,attribcx,lengbp,offset mes10hout_strlocate y,x
; єёЄрэютър ъєЁёюЁр т яючшЎш■ ¤ъЁрэр row=y, column=xah,02hbh,0dh,ydl,x10hlocateDQ
0FF734FAD45672344h
Deler Dw 0DQ 0DW 0
SignR DB 0 DB 0DB ?
DQ 0
Режим экрана, используемый в программе
usemode
EQU 83h
; 10000011b режим 3 с запретом
очистки экрана
ExCode DB 0DB 21,?,21 DUP(?)
STR16 DB 7,?,7 DUP(?)DB 21 DUP (?),13,10,'$' DB
'Переполнение'=$-errorover DB 'Не верный сивол'=$-errorbad DB
'Переполнение',13,10,'$' DB 'Не
верный
символ',13,10,'$'4
DB 'Выберите: новое
деление - N, выход -Esc'
type4len = $-type4 DB '|/-\'
hellomes db
'Программа совместно в резидентом выполняющая деление чисел в формате
64:16',13,10,'результат 64 частное 16 остаток. Деление выполняется на основе
команды div.'
hlen=$-hellomes
First
DB 'Введите
делимое, знакокое 64 битное число'
Flen=$-first
Second
DB 'Введите делитель,
знаковое 16 разрядное число'
Slen=$-second
_del db 'Делимое'=$-_del
_del2 db 'Делитель'=$-_del2
_ost db 'Остаток'=$-_ost
_chast db 'Частное'
clen=$-_chast
nosign
db 'У резидента не
верная сигнатура. Нажмите любую клавишу для выхода.'
nosignlen=$-nosign
divover
DB 'Переполнение
деления.'
divoverlen
= $-divover
noinst
db 'Резидент
отсутствует в памяти. Нажмите любую клавишу для выхода.'
noinstlen=$-noinst
mainmes db
'Выберите Alt+A-деление,
Esc-выход из режима
ожидания'
mainlen=$-mainmes
mes_nocall
DB 'Деление на
выполнено - не была нажата комбинация Alt+A'
mes_nocalllen
= $-mes_nocall
Ostatok db 6
dup (?)
OstatokLEN=$-Ostatok
Chastnoe db
20 dup (?)
ChastnoeLEN =$-Chastnoe
CODESEG
proc
Neg64 ;смена знака
опиисана в резиденте
not [word ptr bx+6][word ptr
bx+4][word ptr bx+2][word ptr bx][word ptr bx],1[word ptr bx+2],0[word ptr
bx+4],0[word ptr bx+6],0
endp
Neg64
;-----------------
proc
Div64 ;деление описано
в резиденте
mov
[SignR],1[SignC],1bx,bxpositive1[SignR]bx:si, [word ptr
Operand+6]si,sipositive2[SignR][SignC]bxbx, offset OperandNeg64bx:dx, dxax,
[word ptr Operand+6]bx[word ptr result+6], axax, [word ptr Operand+4]bx[word
ptr result+4], axax, [word ptr Operand+2]bx[word ptr result+2], axax, [word ptr
Operand]bx[word ptr result], ax[Rem], dx[SignC], 1
je ok1[Rem]:
cmp [SignC],1ok2bx, offset
operandNeg64:Div64
;---------------
proc
mul6410 ;умножение на
10 для перевода из ascii
строки
mov
di,10 ;основание
системы
mov
ax, [word
ptr Operand+6]
;умножим старшую часть
jnc
nocar ;переполнение
ret
nocar:[word ptr Buf+6],ax
ax, [word
ptr Operand+4]
;умножим оставшиеся части
mul
di
add [word
ptr Buf+6]
,dx ;c
учетом переносов
mov [word ptr Buf+4],axax, [word ptr
Operand+2]di[word ptr buf+4] ,dx[word ptr buf+2],axax, [word ptr
Operand]di[word ptr buf+2] ,dx[word ptr buf],axmul6410
;----------------------ADD64
;cложение с числом[word ptr operand],dx[word ptr operand+2],0[word ptr
operand+4],0[word ptr operand+6],0 add64
;-------------------xchg64 ;обмен
cx
mov
cx, [word
ptr si]
;обмениваем по частям с использованием регистра сх
xchg cx, [word ptr di][word ptr
si],cxcx,[word ptr si+2]cx, [word ptr di+2][word ptr si+2],cxcx,[word ptr
si+4]cx, [word ptr di+4][word ptr si+4],cxcx,[word ptr si+6]cx, [word ptr
di+6][word ptr si+6],cxcxxchg64
;---------------------------mov64 ;перемещение
cx
mov
cx, [word
ptr si]
;перемещаем по частям
mov [word ptr di],cxcx,[word ptr
si+2][word ptr di+2],cxcx,[word ptr si+4][word ptr di+4],cxcx,[word ptr
si+6][word ptr di+6],cxcxmov64clear64 ;обнулениеcx[word ptr di],0[word ptr
di+2],0[word ptr di+4],0[word ptr di+6],0cx
endp
clear64
;-------------------
proc decbin
;процедура перевода десятичного числа представленного ascii
строкой в двоичное находящееся в регистре ax
cmp [byte
bx],'-' ;Отрицательное
число?
jne
positive
inc
bx ;Продвинем
указатель и
dec
cx;уменьшим счётчик
цикла
call
conv ;Преобразуем
модуль отрицательного десятичного числа.
;На выходе: ax
- двоичный код, сf=1, если
преобразуемое число превышает значение 65535
jc
badend ;Число > 65535
или не допустимый символ?
cmp
ax,32768
ja
overflow;Число >32768
neg
ax;Сформируем
дополнительный код
js
good;Закончим
преобразование
positive:
call
conv;Преобразуем модуль
положительного десятичного числа.
jc
badend; Число > 65535?
cmp
ax,32767
jbe good;Число<
32767:22,0_str
errorover,overlen,34h
; сообщение о переполнении
badend:
stc;cf=1
jmp
n_good ;Выйдем
из преобразования
good: clc;cf=0_good:ret decbin conv
;конвертацияdx
di ax,ax;Очистим
регистр двоичного числа
mov
di,10;10- основание
системы счисления
cycl: mul
di;dx:ax
= ax*10
jc
over_flow;Переход,
если CF=1
mov
dl,[bx] ;Выберем
очередную ASCII-цифру
sub
dl,30h ;Образуем
двоичное число
cmp dl, 0hBddl, 9h
Bd
add
ax,dx;Промежуточная
сумма
jc
over_flow;Переход,
если CF=1
inc
bx
loop
cycl;Продолжим, если cx>0
clc;Нет,
сбросим флаг CF=1
jmp
last
bd:
locate 22,0
out_str
errorbad,badlen,34h
; сообщение о нецифровом символе
stc last_flow:22,0_str
errorover,overlen,34h ; сообщение о переполнении:di dx conv
proc dec_bin64
;процедура перевода десятичного числа представленного ascii
строкой в двоичное находящееся в регистре ax
cmp [byte
bx],'-' ;Отрицательное
число?
jne
positiveq
inc
bx ;Продвинем
указатель и
dec
cx;уменьшим счётчик
цикла
call
conv64 ;Преобразуем
модуль отрицательного десятичного числа.
;На выходе: ax
- двоичный код, сf=1, если
преобразуемое число превышает значение 65535
jc
badend2;Число > 65535
или не допустимый символ?
cmp [word ptr
Operand+6],8000hoverflow2;Число >32768[word ptr
Operand+4],0000hoverflow2;Число >32768[word ptr
Operand+2],0000hoverflow2;Число >32768[word ptr
Operand],0000hoverflow2;Число >32768bx, offset OperandNeg64;Сформируем
дополнительный
код
good2;Закончим
преобразование
positiveq:
call
conv64 ;Преобразуем
модуль положительного десятичного числа.
jc badend2; Число > 65535?[word
ptr Operand+6],7fffhgood2;Число< 32767[word ptr
Operand+4],0ffffhgood2;Число< 32767[word ptr
Operand+2],0ffffhgood2;Число< 32767[word ptr Operand],0ffffhgood2;Число<
32767:
; print ErrorOver222,0_str
errorover,overlen, 34h ; сообщение о переполнении2:
stc;cf=1
jmp
n_good2;Выйдем
из преобразования
good2:clc;cf=0_good2: dec_bin64
;----------------- conv64
;конвертацияdx didi, offset operandclear64:mul6410;dx:ax =
ax*10over_flow3;Переход, если CF=1di, offset operandsi, offset bufmov64
dl,[bx] ;Выберем
очередную ASCII-цифру
xor
dh,dh
cmp dl, 0hBddl, 9h
Bd
call
add64;Промежуточная
сумма
jc
over_flow3;Переход,
если CF=1
inc
bx
loop
cycl2;Продолжим, если cx>0
clc;Нет,
сбросим флаг CF=1
jmp last3:
; print ErrorBad222,0_str
errorbad,badlen, 34h last_flow3:
; print ErrorOver222,0_str
errorover,overlen, 34h:di dx conv64
;--------------------- Bindec
cx,21;Размер буфера в
байтах
Blank:mov
[byte bx],'
' ;Очистим буфер, т.е. заполним его пробелами
inc bxBlank
bx;Установим адрес
последнего элемента буфера
push [word ptr operand+6]AX, [word
ptr Operand+6] AX,AX;Установим
флаг знака SF
jns
trans
push
bx;Перейдём к
преобразованию, если SF=0
mov
bx, offset
Operand
call
neg64;Изменим знак
pop
bx
trans:
push
bx
mov
bx, 10
call Div64;ax=quot(dx:ax/10),
dx=rem(dx:ax/10) [word
ptr Rem],'0';Сформируем
десятичную ASCII-цифруsi, offset resultdi,
offset operandmov64bxAL, [BYTE REM][byte bx],AL ;Занесём в
буферbx;Движение назад[word ptr Operand+6],0000htrans;Число< 32767[word ptr
Operand+4],0000htrans;Число< 32767[word ptr Operand+2],0000htrans;Число<
32767[word ptr Operand],0000h trans;Число<
32767
pop
ax;Восстановить
исходное число,
or
ax,ax;Установим
флаг знака SF
jns
out_trans;Выходим
из подпрограммы, если SF=0
mov [byte
bx],'-' ;Запишем
знак '-' для отрицательного числа
out_trans: Bindec
;------------
delay
mov
ah,0 ;Функция
"чтения" циклов таймера
int 1Ah
;Получаем значение счетчика циклов в cx:dx
add
dx,9 ;Добавляем 5
сек. к младшему слову в dx
mov
bx,dx
;Запоминаем требуемое значение в bx
и выполняем
;постоянную проверку значений счетчика времени
суток
repeat:int
1Ah ;Вновь
получаем значение счетчика
cmp
dx,bx
;Сравниваем с искомым
jne
repeat
ret
endp
delay
Процедура ожидания (заглушка) Waiting,
реализующая в бесконечном цикле вывод на экран
;вращающегося курсора. Производится фильтрация
нажатия клавиш:
;Резидентом - комбинация Alt-A
- приказ на выполнение процедуру вычисления,
;Программой trans_m
- клавиша Esc - выход из
процедуры Waiting.
Proc Waiting
push
ds
pop
es ; es=ds
(сегмент данных транзитной программы)
window 0,3Bh,24,0,24,7922,0_str
mainmes, mainlen, 03Ah
;Получим позицию курсора, используя функцию 03h
прерывания int 10h
;Вывод на экран спрайта анимации (вращающийся
курсор) путём непосредственного программиро-
;ования памяти. Преобразуем координаты курсора
из системы "строка - столбец" в номер пиксела
;(рег. ах) на экране монитора
;Настроим пару es:di
на адрес вывода
push
es
mov
ax,0B800h
mov
es,ax
mov
di,24*160
mov
si,0 ;Индекс
считывания элементов Sprite
;Вывод в цикле текущего символа строки sprite
@@loop: mov
dh,34h ;красный
по синему
mov
dl,[sprite+si]
;очередной символ
mov [es:di],dx
;вывод на экран
inc
si
and
si,03h ;Цикл
вывода включает все элементы Sprite
mov
bp,2
call
delay ;Временная
задержка
;Проверка буфера клавиатуры без ожидания
(функция 01h, int
16h) на наличие в нём
символа. При
;проверке, возвращаемая в АХ информация не
удаляется из буфера: ZF=1-
буфер пуст, ZF=0-
;в буфере есть сисмволы
mov
ah,01h
int 16h
jz
short @@loop ;Символ
отсутствует
int 16h
; с удалением из буфера. Ожидаем, если буфер пуст
cmp
al,1Bh ;Нажата
Esc?
je
short @@end
;Да, на выход
jmp
short @@loop
;Нет, продолжим вывод анимации
@@end: pop es0,3Bh,22,0,24,79 Waiting Bidec
ax ;Сохраним
знак преобразуемого числа
mov
cx,6;Размер
буфера в байтах
Blank2: mov [byte bx],' ' ;Очистим
буфер,
т.е.
заполним
его
пробеламиbxBlank2
dec
bx;Установим адрес
последнего элемента буфера
mov
di,10 ;Введём
основание десятичной системы счисления
or
ax,ax ;Установим
флаг знака SF
jns
trans2 ;Перейдём к
преобразованию, если SF=0
neg
ax ;Изменим
знак
trans2: sub
dx,dx ;Сделаем
dx=0
div di ;ax=quot(dx:ax/10),
dx=rem(dx:ax/10)dl,'0' ;Сформируем
десятичную
ASCII-цифру[byte
bx],dl ;Занесём в
буфер
bx ;Движение
назад
or
ax,ax ;Преобразование
закончено?
jnz
trans2 ;Повторить,
если АХ>0
pop
ax ;Восстановить
исходное число,
or
ax,ax ;с
целью определения его знака
jns
out_trans2 ;Выходим
из подпрограммы, если SF=0
mov [byte
bx],'-' ;Запишем
знак '-' для отрицательного числа
out_trans2: ret Bidec:ax,
@datads,ax es,ax
; es=ds
getmode
; сохранение старого режима
setmode
usemode ; установка нового
режима
allagain:
window 0,03Bh,0,0,24,79
;главное окно
window 0, 0F0h,7,7,7,7+21
;окна ввода
window 0, 0F0h,7,7+40,7,7+46
window 0, 0F0h,10,7,10,7+21
;окна вывода
window 0, 0F0h,10,7+40,10,7+46
locate 0,0
;подписи к окнам
out_Str hellomes, hlen, 03bh6,7_Str
_del, hd, 03bh6,7+40_Str _del2, hd2, 03bh9,7_Str _chast, clen, 03bh9,7+40_Str
_ost, olen, 03bh dx,dx
mov
ax, 0c800h
;проверка на наличие резидента
int 2fhal, 0ffh ;наш..?no
dx, 8888h
;совпала сигнатура?
jne nosignature:0,
0F0h,7,7,7,7+2124,0_Str first, flen, 03Ah7,7dx,offset Str64ah,0Ah21h ;ввод
делимогоch,chcl,[str64+1]bx,offset str64+2
dec_bin64
;перевод делимого
jc
again1 ;если ошибка то
повторить ввод
window 0,03Bh,22,0,22,79:0,
0F0h,7,7+40,7,7+4624,0_Str second, slen, 03Ah7,7+40dx,offset Str16ah,0Ah ;ввод
делителя21hch,chcl,[str16+1]bx,offset str16+2decbin ;перевод делителя
again2 ;если ошибка то
перевод
mov [Deler],ax0,03Bh,22,0,22,79:
mov
si, offset
operand ;подготовка к
передачи данных резуденту
mov
ax, 0c802h
;передача
int 2fh
call
waiting ;заглушка
mov
ax, 0c804h
;подготовка к получению данных
push dsesdi, offset Result
2fh
cmp
ch, 0ffh
;произведена активаций...?
je
nocall
cmp
cl, 0 ;нет ошибок..?
je results22,0_str
divover,divoverlen ,34h ; вывод ошибкиPrintQuestion:ax, [Rem]bx, offset
Ostatokbidec ;преобразование остатка10, 47_str Ostatok, Ostatoklen, 0F0h ;вывод
остаткаdi, offset Operandsi, offset Resultmov64bx, offset chastnoe ;преобразование
частногоBindec10, 7_str Chastnoe+1, Chastnoelen, 0F0h ;вывод
частногоprintquestion:22,0_str mes_nocall,mes_nocalllen,34h ; сообщение о том,
что не была нажата комбинация Alt-A:0,3bH, 24,0,24,7924,0_str
type4,type4len,3Ah ; вывод подсказкиah,00h ; ввод символа16hal,'N' ;
'n'?allagain ; новый вводal,1Bh ; ESCPrintQuestionExitExit:
22,0
out_str
nosign,nosignlen,034h
; сообщение о присутствии резидента с той же функцией, но другой сигнатурой
readkeyexit:
22,0
out_str
noinst,noinstlen,034h
; сообщение об отсутствии резидента в памяти
readkey
Exit: setmode
[oldmode]
mov
ah,4ch
;Функция DOS-выход из
программы
mov
al,[ExCode];Возврат
кода ошибки
int 21h
;Вызов DOS. Останов
прогр.
END
Start ;Конец
программы/точка входа