3. Интерпретатор управляющей программы.
Zad3: ClearScreen
tt1: ClearScreen ;очистка экрана
Locate 0,0 ;курсор в начало экрана
Call _Wwod
Locate 0,1
mov ah,40h ;вывести на экран символьный текст
mov bx,01 ;в количестве, заданном в сх
mov dx,OFFSET Bufer ;из буфера с именем Bufer
int 21h ;с помощью прерывания с номером ;21h
mov di,OFFSET Bufer ;адрес памяти с УП
Call Interpr ;вызов интерпретатора
KeyWait
ClearScreen ;очистка экрана
Locate 1,0
PrintXY 0,4,RT
KeyWait
cmp al,'y'
jz tt1
cmp al,'Y'
jz tt1
KeyWait
jmp menu ;выход в меню программы karkas
Результат выполнения:
Использованные в программе интерпретатора макрокоманды:
PrintBin MACRO data ;вывод двоичного числа data
mov ax,data ;в десятичной форме.
CALL _PrintBin ;cтарший бит – знаковый.
ENDM
;==============================
Asc_to_Bin MACRO data ;преобразование ASCII числа длиной AscLen символов
push ax ;с размещением
CALL _AscToBin ;в слове по адресу BinVal
mov ax,[BinVal] ;в беззнаковое двоичное
mov [data], ax ;по адресу data
pop ax
ENDM
;==============================
Использованные процедуры:
;Преобразование из символьного ASCII-формата в двоичный
;вход – поле символов по адресу AscVal
;число символов по адресу AscLen
;множитель в Mult10, начальное значение =1
;выход – двоичное беззнаковое число по адресу BinVal
PROC _AscToBin
mov [Mult10],1 ;начальная установки множителя
mov [BinVal],0 ;очистить приемник
push cx ;сохранить cx
mov cx,10 ;фактор умножения
lea si,AscVal-1 ;адрес байта
mov bx,[AscLen] ;длина символьной строки
b20: mov al,[si+bx] ;младший цифровой символ
and ax,000fh ;в ах – младшее число
mul [Mult10] ;в ах произведение
add [BinVal],ax ;сложить с исходным
mov ax,[Mult10] ;умножить 1 на 10
mul cx
mov [Mult10],ax ; множитель равен 10
dec bx ;адрес следующего символа
jnz b20 ;если не нуль – повторить умножение на 10
pop cx ;восстановить cx
ret
ENDP
;==============================
;процедура вывода на монитор двоичного
;вход: в регистре АХ – двоичное число со знаком
;выход: преобразование двоичного числа co знаком в десятичное
;и вывод на экран в текущей позиции курсора
PROC _PrintBin
push ax ;сохранение
push bx ;регистров
push cx
push dx
mov [Znak], ‘+’ ;установить символ «+»
test ax,8000h ;проверка на знак
jz @@1 ;если положительное – далее
and ax,7ffffh ;иначе – изменить знак двоичного
mov [Znak], ‘-‘ ;и установить символ «-»
@@1: Tout [Znak] ;символ знака – на экран
mov cx,4 ;счетчик на 4 цикла
mov bx,10 ;делитель =10
@@2: xor dx,dx ;очистить dx
div bx ;делить ax на 10
add dl,30h ;остаток – преобразовать в символ
mov dh,14 ;установить атрибут символа
push dx ;оба байта регистра dx – в стек
loop @@2 ;повторить 4 раза
add al,30h ;последнее частное
Tout al ;на экран
mov bh,0 ;страница видео
mov bl, 4dh ;атрибут
mov cx,4 ;счетчик на 4
@@3: pop ax ;символ из стека в ax
int 10h ;вывод на экран
loop @@3 ;4 раза (остатки)
pop dx ;восстановить
pop cx ;использованные
pop bx ;регистры
pop ax
ret
ENDP
;==============================
PROC Interpr ;УП по адресу Bufer
;инициализация переменных
mov [Er],0 ;кол-во ошибок
mov [X],0
mov [N],0
mov [M],0
mov [M02],0
mov [LenKadr],0
mov [ZnakX],0
mov [DiN],di ;адрес начала интерпретируемого кадра
mov bl,[byte ptr di]
cmp bl,'N' ;это N?
jz N11
inc [Er]
Locate 0,19 ;да, дальше
Print NetN ;Error
jmp Kon ;inc [Er]
PROD:
cmp bl,13 ;это Enter?
jnz X11 ;начать опрос и продолжить
jmp Kon
;=============
N11:
cmp bl,'N' ;это N?
jnz N11
mov si,OFFSET AscVal;
mov cx,0 ;счетчик цифр
N21:
inc di ;адрес очередного байта УП
mov bl,[byte ptr di] ;забираем байт
cmp bl,'-' ;это '-'?
jz N31
cmp bl,'+'
jz N31 ;это '+'?, взять очередной байт
cmp bl,'0' ;этот символ <0
jl N41
cmp bl,'9' ;этот символ>9
jg N41
mov [si],bl ;эдесь цифра, в буфер AscVal
inc cx ;[AscLen], число проанализированных цифр
inc si
cmp cx,4 ;превысили 4 цифр?
jz N0
jmp N21 ;за новым символом
N0:
inc [Er] ;добавить ощибку
jmp N21
N31:
inc [Er] ;mov [ZnakX],'-' ;знак -Х
jmp N21 ;PROD;Kon ;выйти из процедуры
N41: push bx ;сохранить следующий взятый символ
mov [AscLen],cx ;длина буфера AscVal
Asc_to_Bin [N] ;преобразовать в двоичное и поместить в N
pop bx
jmp PROD
;==============
;Обработка слова УП по Х
X11:
cmp bl,'X' ;это Х?
jnz M11
mov si,OFFSET AscVal;
mov cx,0 ;счетчик цифр
X21:
inc di ; адрес очередного байта УП
mov bl,[byte ptr di] ;забираем байт
cmp bl,'-' ;это '-'?
jz X31
cmp bl,'+'
jz X21 ;это '+'?, взять очередной байт
cmp bl,'0' ;этот символ <0
jl X41
cmp bl,'9' ;этот символ>9
jg X41
mov [byte ptr si],bl ;здесь цифра, в буфер AscVal
inc cx ;[AscLen], число проанализированных цифр
inc si
cmp cx,6 ;превысили 6 цифр?
jz X0
jmp X21 ;за новым символом
X0: inc [Er] ;добавить ощибку
jmp X21 ;PROD;Kon
X31: mov [ZnakX],'-' ;знак -Х
jmp X21 ;за очередным байтом УП
X41: push bx ;сохранить взятый символ
;Bin_to_Dec cx ;коорд Х на зкран
;pop cx
mov [AscLen],cx ;длина буфера AscVal
Asc_to_Bin [X] ;преобразовать в двоичное и поместить в Хk
pop bx
jmp PROD
;===============
;Обработка слова УП по M
M11:
cmp bl,'M' ;это MT?
jz q3 ;U11;
jmp U11
q3: mov si,OFFSET AscVal
mov cx,0 ;счетчик цифр
M21:
inc di ; адрес очередного байта УП
mov bl,[byte ptr di ;забираем байт
cmp bl,'-' ;это '-'?
jz M31
cmp bl,'+'
jz M0 ;это '+'?, взять очередной байт
cmp bl,'0' ;этот символ <0
jl M41
cmp bl,'9' ;этот символ>9
jg M41
mov [byte ptr si],bl ;здесь цифра, в буфер AscVal
inc cx ;[AscLen], число проанализированных цифр
inc si
cmp cx,3 ;превысили 2 цифр?
jz M0
jmp M21 ;за новым символом
M0: inc [Er] ;добавить ощибку
jmp M21 ;PROD
M31: inc [Er] ;знак - M
jmp M21 ;PROD
M41: push bx ;сохранить взятый символ
mov [AscLen],cx ;длина буфера AscVal
Asc_to_Bin [M] ;преобразовать в двоичное и поместить в M
pop bx
cmp [M],2
jnz @@7
mov ax,[M]
mov [M02],ax
@@7:
jmp PROD
;====================
U11: inc [Er]
Locate 0,19
Print NedopSim ;недопустимый символ
;конец форматирования переменных, анализ:
Kon:
mov ax,[X] ;рассчитать суммарное перемещение в кадре
mov [S],ax
mov ax,di
sub ax,[DiN] ;адрес конца интерпретируемого кадра
inc ax ;учесть LF
mov [LenKadr],ax ;длина текущего кадра
push di
Locate 5,8
Print Errors ;показать число ошибок
Bin_to_Dec [Er];
cmp [Find],0
jnz s
jmp rr
s: KeyWait
Locate 0,12
Print NameKadr
Locate 0,13
Bin_to_Dec [N] ;коорд N на экран
Bin_to_Dec [X] ;коорд X на экран
Bin_to_Dec [M] ;коорд M на экран
Bin_to_Dec [ZnakX]
rr: pop di ;конечный адрес кадра
ret
ENDP
;====================
Необходимые данные в сегменте данных:
DataSeg ;сегмент данных
ExSg dw 0 ;хранение регистра ES
FName db 63 DUP (0) ;поле имени (пути) файла
BuferData db 4096 DUP(0) ;буфер для размещения файла
FileLen dw 0 ;длина файла
Handle dw 0 ;номер (дескриптор) файла
Hand dw 0
FileNumber dw 0
LenStr dw ;длина строки
AscVal DB 6 DUP(' ') ;число в ASCII коде
BinVal DW 0
AscLen DW 0
Mult10 DW 1
X DW 0 ;текущие значения
S DW 0
ZnakX DW 0 ;признак+
N DW 0
M DW 0
M02 DW 0 ;конец программы
Er DW 0
FileLen DW 0
DiN DW 0 ;начальный адрес кадра
LenKadr DW 0 ;длина текущего кадра, устанавливается интерпр.