Міністерство освіти і науки
Національний університет «Львівська політехніка»
Кафедра ЕОМ
Звіт
до лабораторної роботи № 6
з дисципліни: “ Засоби системного програмування”
на тему: “ Використання макрокоманд та процедур.
Ввід даних з клавіатури та вивід результату на екран.”
Мета: набути навиків написання макрокоманд та процедур на Асемблері, освоїти способи передачі параметрів. Реалізувати ввід та вивід даних в десятковій системі числення.
Короткі теоретичні відомості
Макрозасоби
Для кожної закодованої команди асемблер генерує одну машинну команду. Але для кожного закодованого оператора компіляторної мови Pascal чи C генерується один чи більш (частіше багато) команд машинної мови. У цьому відношенні можна вважати, що компіляторна мова складається з макрооператорів.
Асемблер також має макрозасоби, але макроси тут визначаються програмістом. Для цього задається ім'я макросу, директива MACRO, різні асемблерні команди, що повинний генерувати даний макрос і для завершення макровизначення - директива MEND. Потім у будь-якім місці програми, де необхідне виконання визначених у макрокоманді команд, досить закодувати ім'я макросу. У результаті асемблер згенерує необхідні команди.
Використання макрокоманд дозволяє:
- спростити і скоротити вихідний текст програми;
- зробити програму більш зрозумілої;
- зменшити кількість можливих помилок кодування.
Прикладами макрокоманд можуть бути операції вводу-виводу, пов’язані з ініціалізацією регістрів і виконання переривань перетворення ASCII і війкового форматів даних, арифметичні операції над довгими полями, обробка рядкових даних, ділення за допомогою віднімання.
Ввід з клавіатури
1. Використання групи функцій переривання DOS INT 21H, при цьому номер функції цього переривання вказується в регістрі AH:
AH=01: Ввід символу з клавіатури з еховідображенням. Дана функція повертає значення в регістрі AL. Якщо вміст AL не дорівнює нулю, то воно являє собою стандартний ASCII- cимвол, наприклад, букву або цифру. Нульове значення в регістрі AL свідчить про те, що на клавіатурі була натиснута спеціальна функціональна клавіша, наприклад, Номе, F1 або PgUp. Для визначення скен-коду клавіш, необхідно повторити виклик функції Дана функція реагує на запит Ctrl/Break.
AH=07: Прямий ввід із клавіатури без еховідображення. Дана функція працює аналогічно функції 01 із двома відмінностями: введений символ не відображається на екрані, тобто немає еха, і відсутня реакція на запит Ctrl/Break.
AH=08: Ввід із клавіатури без еховідображення. Дана функція діє аналогічно функції 01 з однією відмінністю: введений символ не відображається на екрані.
AH=0Ah - буферизований ввід стрічки з еховідображенням;
Для використання даної функції область вводу вимагає наявності cписку параметрів, що містить поля, які необхідні при виконанні команди INT. По-перше, повинна бути визначена максимальна довжина тексту, що вводить. Це необхідно для попередження користувача звуковим сигналом, якщо набрано занадто довгий текст; символи, що перевищують максимальну довжину не приймаються. По-друге, у списку параметрів повинне бути певне поле, куди команда повертає дійсну довжину уведеного тексту в байтах. . По-третє, повинно бути виділено місце під введені символи. Для запиту на ввід необхідно помістити в регістр AH номер функції - 10 ( 0AH), у регістр DX завантажити адресу списку параметрів і виконати INT 21H. Команда INT очікує поки користувач не введе із клавіатури текст, перевіряючи при цьому, щоб кількість введених символів не перевищувало максимального значення, зазначеного в списку параметрів. Для вказівки кінця вводу користувач натискає клавішу Enter. Код цієї клавіші (0Dh) також заноситься в поле вводу. Таким чином, дійсна довжини тексту, що вводиться, є на одиницю менша від максимально передбаченої.
AH=0Bh: Перевірка стану клавіатури. Дана функція повертає FFh у регістрі AL, якщо ввід із клавіатури можливий, у іншому випадку - 00. Цей засіб пов’язане з функціями 01, 07 і 08, які не очікують вводу з клавіатури.
2. Посимвольний ввід шляхом звертання до драйвера BIOS за допомогою переривання INT 16H
Команда BIOS INT 16H виконує спеціальну операцію, яка відповідно до коду в регістрі AH забезпечує наступні три функції вводу клавіатури.
AH=00: Читання символу. Дана функція поміщає в регістр AL черговий ASCII символ, введений із клавіатури, і встановлює скен код у регістрі AH.. Якщо на клавіатурі натиснута одна з спеціальних клавіш, наприклад, Номе або F1, то в регістр AL заноситься 00. Автоматичного еховідображення символу на екран не відбувається.
AH=01: Визначення наявності введеного символу. Дана функція скидає прапорець нуля (ZF=0), якщо є символ для читання з клавіатури; черговий символ і скен-код будуть поміщені в регістри AL і AH, відповідно і даний елемент залишиться в буфері.
AH=02: Визначення поточного стану клавіатури.
3. Звертання до клавіатури, як до файлу.
Це здійснюється шляхом використання функцій 3Fh переривання 21h
При цьому у регістр CX заноситься кількість байт для вводу, а в регістр DX - адреса області вводу. У результаті успішного виконання операції вводу очищається прапорець переносу (CF) і в регістр AX встановлюється дійсна кількість байт, що беруть участь в операції. При неуспішній операції встановлюється прапорець CF, а код помилки (в даному випадку 6) заноситься в регістр AX. Оскільки регістр AX може містити як довжину даних, так і код помилки, то єдиний спосіб визначити наявність помилки – перевірити прапорець CF, хоча помилки читання із клавіатури й виводу на екран - не часті.
Після введеного тексту безпосередньо слідує символ повороту каретки (0Dh), що був введений, і символ кінця рядка (0Ah), що не був введений. Тому, максимальна кількість символів і розмір області вводу повинні передбачати місце для двох додаткових символів. Якщо буде введено менше символів ніж максимальне значення, то в пам'яті, після введених символів збережуться колишні значення. У результаті успішної операції буде очищений прапорець CF (що можна перевірити) і в регістрі AX буде встановлена кількість байт, введених із клавіатури(кількість введених символів +2).
Завдання:
1. Створити *.exe програму, яка реалізовує обчислення, заданого варіантом виразу над даними, введеними в десятковій системі і результат виводить на екран в десятковій формі.
Програма повинна складатися з трьох основних підпрограм:
процедура вводу - забезпечує ввід даних з клавіатури в десятковій формі і їх перевід у двійкове значення ;
процедура безпосередніх обчислень – здійснює всі необхідні арифметичні дії у двійковій системі;
процедура виводу – забезпечує перевід війкового результату у десятковий формат та вивід на екран.
Передача параметрів може здійснюватися довільним чином. Кожна з перерахованих процедур може містити довільну кількість додаткових підпрограм.
Вхідні операнди А, В, С, D, E, F вважати беззнаковими і довжиною в байтах, згідно з індексу. К – константа, довжина якої визначається значенням(згідно варіанту).
2. Переконатися у правильності роботи кожної процедури зокрема та програми загалом.
3. Скласти звіт про виконану роботу з приведенням тексту програми та коментарів до неї.
4. Дати відповідь на контрольні запитання.
ІНДИВІДУАЛЬНЕ ЗАВДАННЯ (ВАРІАНТ 11):
№
Вираз
K
11
X=(A4-B3-K)*D1+E4/F2
311
Текст програми:
DOSSEG
.MODEL SMALL
MY_MUL MACRO X,Y,Z ;макрос
mov z,0
mov z+2,0
MOV ax,X
MUL Y
MOV Z,ax
MOV Z+2,dx
MOV AX,X+2
MUL Y
ADD Z+2,AX
mov ax,Z
mov dx,Z+2
ENDM
.STACK 100h
.DATA
;A dd 11223344h
;B dd 32321212h
;D db 3234h
;E dd 3232h
;F dw 23h
A dd 0
B dd 0
D db 0
E dd 0
F dw 0
K EQU 311h
temp1 dw 0
temp2 dw 0
temp3 dw 0
temp4 dw 0
X dd 0
X_Str db 10 dup (0)
TempStr db 10 dup (0)
TempBin dw 0,0
MaxLen dw 0
X_div2 dw 0,0
Y_div2 dw 0
MESSG_X DB 13,10,'X=(A(4)-B(3)-K)*D(1)+E(4)*F(2) K=311h','$'
MESSG_A DB 13,10,'A = ','$'
MESSG_B DB 13,10,'B = ','$'
MESSG_D DB 13,10,'D = ','$'
MESSG_E DB 13,10,'E = ','$'
MESSG_F DB 13,10,'F = ','$'
MESSG_X1 db 13,10,'X = ','$'
erStr1 db 13,10,'Data not input_variable',13,10,'$'
erStr2 db 13,10,'Incorrectly data ',13,10,'$'
erStr2_1 db 13,10,' F = 0 --> divide by zero ',13,10,'$'
erStr3 db 13,10,'Data is too long ',13,10,'$'
Mult10 dw 1,0
my_z dw 0,0
.CODE
start:
mov ax,@data
mov ds,ax
call input ;процедура вводу з клавіатури
call calculation ;процедура обчислення виразу
call output ;процедура виводу результату
mov ah,01
int 21h
mov ah,4Ch
int 21h
;////////////////////////////////////////////
input proc ; процедура вводу
LEA DX,MESSG_X ; lea завантажує ефективну адресу MESSG_X
MOV AH,09
INT 21H
LEA DX,MESSG_A
MOV AH,09
INT 21H
mov di,offset A
mov MaxLen,9
mov cx,MaxLen
call input_variable
LEA DX,MESSG_D
MOV AH,09
INT 21H
mov di,offset D
mov MaxLen,3
mov cx,MaxLen
call input_variable
cmp D,0 ; перевіряю чи D==0, ,бо а С буде відбуваись ділення
jne next_step
mov ah,09
mov dx, offset erStr2_1
int 21h
mov ah,4Ch
int 21h
next_step:
LEA DX,MESSG_B
MOV AH,09
INT 21H
mov di,offset B
mov MaxLen,9
mov cx,MaxLen
call input_variable
LEA DX,MESSG_E
MOV AH,09
INT 21H
mov di,offset E
mov MaxLen,9
mov cx,MaxLen
call input_variable
LEA DX,MESSG_F
MOV AH,09
INT 21H
mov di,offset F
mov MaxLen,5
mov cx,MaxLen
call input_variable
ret
input endp
;///////////////////////////////////////////
calculation proc
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
;1) temp1 = A-B
mov ax,word ptr A
mov dx,word ptr B
sub ax,dx
mov temp1,ax
;2)temp2 = temp1+K
mov ax,temp1
add ax, K
mov temp2, ax
;3) temp3=D*temp2
mov al, byte ptr D
mul temp2
mov word ptr temp3,ax
;4) temp4 = E / F
mov ax, word ptr E
mov dx, word ptr [E+2]
div F
mov temp4,ax
;5) X=temp3*temp4
mov ax, temp3
mul temp4
mov word ptr X,ax
mov word ptr [X+2],dx
ret
calculation endp
;///////////////////////////////////////////
input_variable PROC
mov si,0
In_00: mov ah,01
int 21h
cmp al,0Dh
je In_1
In_0: mov dl,al
call CHECK_BYTE
mov TempStr[si],dl
inc si
loop In_00
In_1: push si
dec si
cmp cx,MaxLen
jne In_2
call Err1
In_2: mov bh,0
mov bl,TempStr[si]
MY_MUL Mult10,bx,my_z
add TempBin,ax
adc TempBin+2,dx
mov bh,0
mov bl,10
MY_MUL Mult10,bx,my_z
mov Mult10,ax
mov Mult10+2,dx
dec si
cmp si,0
jge In_2
mov ax, TempBin
mov dx,TempBin+2
pop si
cmp si,MaxLen
jl In_3
cmp MaxLen,10
jl In_2_1
js In_Err
cmp dx,0FFFFh
ja In_Err
jmp In_3
In_2_1: cmp MaxLen,5
jl In_2_2
cmp dx,00
ja In_Err
cmp ah,0ffh
ja In_Err
jmp In_3
In_2_2: cmp ax,00FFh
jbe In_3
In_Err: LEA DX,erSTR3
MOV AH,09
INT 21H
mov ah,4Ch
int 21h
In_3: mov [di],ax
mov [di+2],dx
mov TempBin,0
mov TempBin+2,0
mov Mult10,1
mov Mult10+2,0
RET
input_variable ENDP
Err1 PROC
PUBLIC Err1
LEA DX,erSTR1
MOV AH,09
INT 21H
mov ah,4Ch
int 21h
RET
Err1 ENDP
CHECK_BYTE PROC
PUBLIC CHECK_BYTE
sub dl,30h
cmp dl,00
jl ErS
cmp dl,0Ah
jl GO
ErS: LEA DX,erSTR2
MOV AH,09
INT 21H
mov ah,4Ch
int 21h
GO: RET
CHECK_BYTE ENDP
;///////////////////////////////////////////////////
MY_DIV2 proc
sub cx,cx
sub bx,bx
mov dx,X_div2+2
mov ax,X_div2
M2_D1:
cmp dx,Y_div2
jb M2_D3
sub ax,Y_div2
sbb dx,00
sbb bx,00
add cx,01
adc bx,0
jmp M2_D1
M2_D3:
div Y_div2
add cx,ax
adc bx,00
ret
MY_DIV2 ENDP
;///////////////////////////////////////////
output PROC
mov di,0
mov Y_div2,10
mov cx, word ptr X
mov bx, word ptr [X+2]
O_1: mov X_div2,cx
mov X_div2+2,bx
call my_div2
add dl,30h
mov X_Str[di],dl
inc di
cmp bx,0
ja O_1
cmp cx,10
jae O_1
add cl,30h
mov X_Str[di],cl
mov dx,offset MESSG_X1
mov ah,09
int 21h
O_2: mov dl,X_Str[di]
mov ah,02h
int 21h
dec di
jge O_2
ret
output ENDP
;///////////////////////////////////////////
end start
end
Обчислення:
X = 11223344 - 32321212 / 3234 + 8976+3232* 23= 11296662
Результати роботи програми:
/Рис.1 Результат виконання програми
/
Рис.2. Результат виконання програми при діленні на нуль
/
Рис.3. Результат виконання програми при помилковому вводі
/
Рис.4. Результат виконання програми при спробі ввести занадто велике число
Висновок: Під час виконання даної лабораторної роботи, я навчився описувати та використовувати макрокоманди та процедури в мові ассемблера, освоїв способи передачі параметрів, організував ввід та вивід даних в десятковій системі числення.