Лабораторна робота 9.
Тема: Процедури мовою асемблера
Ціль: Ознайомиться з особливостями організації процедур на асемблері і способами предачі параметрів у процедури.
Даны два массива однобайтовых чисел без знака. Найти сумму их максимальных элементов.
Опишем нахождение максимального элемента массива процедурой.
Формальными параметрами процедуры являются
1) начальный адрес массива
2) количество элементов массива
Будем передавать параметры через регистры. Адрес массива - через регистр BX
Кол-во элементов - через CX
Результат возвращаем основной программе через AL (эл-ты однобайтовые).
Masm
model small
.stack 128
.data
n equ 10
m equ 15
mas1 db n dup (?)
mas2 db m dup (?)
; процедура находит максимальный элемент массива
; адрес массива находится в регистре BX
; кол-во элементов - в CX
; результат возвращаем через AL
max proc
mov al,0 ;
sled: cmp [bx],al
jle new
mov al,[bx]
new: inc bx
loop sled
ret
max endp
start: . . .
lea bx,mas1
mov cx,n
call max ; результат в al
mov dl,al
lea bx,mas2
mov cx,m
call max
add dl,al
. . .
end start
Лабораторна работа 10-11.
Тема. Введення/виведення даних.
Ціль: Ознайомитися з методами введення даних з клавіатури та методами виведення даних на екран.
Приклад 1
format pe
; dosoutl. asm
; Виводить на екран усі ASCII-символи
;
org 100h ; початок Сома-файлу
use16
mov cx, 256 ; вивести 256 символів
mov dl,0 ; перший символ - з кодом 00
mov ah,2 ; номер функції DOS “вивід символу”
cloop: int 21h ; виклик DOS
inc dl ; збільшення DL на 1 - наступний символ
test dl,0Fh ; якщо DL не кратний 16,
jnz continue_loop ; продовжити цикл,
push dx ; інакше: зберегти поточний символ
mov dl,0Dh ; вивести CR
int 21h
mov dl,0Ah ; вивести LF
int 21h
pop dx ; відновити поточний символ
continue_loop:
loop cloop ; продовжити цикл
ret
Приклад 2
; biosout. asm
; Виводить на екран усі ASCII-символи без винятку
format pe
org 100h ; Початок Сома-файлу
use16
start:
mov ax,0003h
int 10h ; Відеорежим 3 (очищення екрана
; і установлення курсору в 0, 0)
mov dx,0 ; DH і DL будуть використовуватися
; для збереження положення курсору.
; Початкове положення - 0,0
mov si,256 ; SI буде лічильником циклу
mov al,0 ; Перший символ - з кодом 00h
mov ah,9 ; Номер відеофункції “вивід символу з атрибутом”
mov cx,1 ; Виводиться один символ за раз
mov bl,00011111b
; атрибут символу - білий на синьому
cloop:
int 10h ; Вивести символ на екран
push ax ; Зберегти поточний символ і номер функції
mov ah,2 ; Номер відеофункції 2 -
; змінити положення курсору
inc dl ; Збільшити поточний стовпець на 1
int 10h ; Перемістити курсор
mov ax,0920h; АН = 09, AL = 20h (ASCII-код пробілу)
int 10h ; Вивести пробіл
mov ah,2 ; Номер відеофункції 2
inc dl ; Збільшити стовпець на 1
int 10h ; Перемістити курсор
pop ax ; Відновити номер функції в ah
; і поточний символ у al
inc al ; Збільшити AL на 1 - наступний символ
test al,0Fh ; Якщо AL не кратний 16,
jnz continue_loop
; продовжити цикл,
push ax ; інакше - зберегти номер функції
; і поточний символ
mov ah,2 ; Номер відеофункції 2
inc dh ; Збільшити номер рядка на 1
mov dl,0 ; Стовпець = 0
int 10h ; Установити курсор на початок наступного рядка
pop ax ; Відновити номер відеофункції
; і поточний символ
continue_loop:
dec si ; Зменшити SI на 1,
; якщо він не став нулем - продовжити
jnz cloop ; CX використовується усередині циклу,
; так що не можна використовувати команду LOOP
; для його організації
ret ; Завершення Сома-файлу
Приклад 3
; dosinl. Asm
format pe
org 100h ; початок Сома-файлу
use16
start:
mov dx, messagel
mov ah,9
int 21h ; вивести запрошення до введення message1
mov dx, buffer
mov ah,0Ah
int 21h ; вважати рядок символів у буфер
mov dx, crlf
mov ah,9
int 21h ; переклад рядка
; переклад числа в ASCII-форматі з буфера в бінарне число в АХ
xor di, di ; DI = 0 - номер байта в буфері
xor ax, ax ; АХ = 0 - поточне значення результату
mov cl,[blength]
xor ch, ch
xor bx, bx
mov si, cx ; SI - довжина буфера
mov cl,10 ; CL = 10, множник для MUL
asc2hex:
mov bl, byte [bcontents+di]
sub bl,'0' ; цифра = код цифри - код символу “0”,
jb asc_error ; якщо код символу був менше, ніж код “0”,
cmp bl,9 ; або більше, ніж “9”,
ja asc_error ; вийти з програми з повідомленням про помилку,
mul cx ; інакше: помножити поточний результат на 10,
add ax, bx ; додати до нього нову цифру,
inc di ; збільшити лічильник
cmp di, si ; якщо лічильник+1 менше числа символів -
jb asc2hex ; продовжити (лічильник вважається від 0)
; вивід на екран рядка message2
push ax ; зберегти результат перетворення
mov ah,9
mov dx, message2
int 21h
pop ax
; вивід на екран числа з регістра АХ
push ax
xchg ah, al ; помістити в AL старший байт
call print_al ; вивести його на екран
pop ax ; відновити в AL молодший байт
call print_al ; вивести його на екран
ret ; завершення Сома-файлу
asc_error:
mov dx, err_msg
mov ah,9
int 21h ; вивести повідомлення про помилку
ret ; і завершити програму
; Процедура print_al
; виводить на екран число в регістрі AL
; у шестнадцатеричном форматі,
; модифікує значення регістрів АХ і DX
print_al:
mov dh, al
and dh,0Fh ; DH - молодші 4 біти
shr al,4 ; AL - старші
call print_nibble ; вивести старшу цифру
mov al, dh ; тепер AL містить молодші 4 біти
print_nibble: ; процедура виводу 4 бітів (шестнадцатеричной цифри)
cmp al,10 ; три команди, що переводять цифру в AL
sbb al,69h ; у відповідний ASCII-код
das ; (див. опис команди DAS)
mov dl, al ; код символу в DL
mov ah,2 ; номер функції DOS в АН
int 21h ; вивід символу
ret ; цей RET працює два рази - один раз
; для повернення з процедури print_nibble,
; викликаної для старшої цифри,
; і другий раз - для повернення з print_al
messagel db “Десяткове число: $"
message2 db “Шестнадцатеричное число: $"
err_msg db “Помилка введення”
crlf db 0Dh,0Ah,'$'
buffer db 6 ; максимальний розмір буфера введення
blength db ? ; розмір буфера після зчитування
bcontents: ; уміст буфера розташовується за
; кінцем Сома-файлу
Лабораторная работа №6
; multi-segment executable file template.
;linclude 'emu8086.inc'
;data segment
; add your data here!
pkey db "press any key...$"
x db 0Ch ; x=a+2b
y db ? ; y=2c-a
a1 db 30
a2 db 250
b1 db 9
b2 db 106
c1 db 7
c2 db -3
z db ? ; z=(x-y)+2
;ends
;stack segment
dw 128 dup(0)
;ends
;code segment
start:
; set segment registers:
mov ax, a1
mov ds, ax
mov es, ax
; printn "Urovnenie (R=x-y^z)"
mov ah, b1
mov bh, 2
mov al, ah
xor ah, ah
mov bl, bh
xor bh, bh
mov ch, a1
mov cl, ch
xor ch, ch
mul bx
add ax, cx
push cx
push ax
; print "x="
; call print_num
; printn
mov dl, c1
xor dh, dh
mov ax, dx
mul bx
sub ax, cx
mov bx, ax
push bx
; print "y="
; call print_num
; printn
pop bx
pop ax
mov dx, ax
sub ax, bx
add ax, 2
; print "z="
; call print_num
; printn
mov di, ax ; z
mov ax, dx
push bx ; y
; push di ; z
push ax ; x
mov dx, bx
mov ax, dx
mov cx, di
mov di, dx
dec cx
A:
mul ax
; loop [a]
mov bx, ax
; print "y^z="
;; printn
pop ax
sub ax, bx
; print "R1="
; call print_num
; printn
; ------------------------------------------------------------------ part 2
mov ah, b2
mov bh, 2
mov al, ah
xor ah, ah
mov bl, bh
xor bh, bh
mov ch, a2
mov cl, ch
xor ch, ch
mul bx
add ax, cx
push cx
push ax
; print "x="
; call print_num
; printn
mov dl, c2
xor dh, dh
mov ax, dx
mul bx
sub ax, cx
mov bx, ax
push bx
; print "y="
; call print_num
; printn
pop bx
pop ax
mov dx, ax
sub ax, bx
add ax, 2
; print "z="
; call print_num
; printn
mov di, ax ; z
mov ax, dx
push bx ; y
; push di ; z
push ax ; x
mov dx, bx
mov ax, dx
mov cx, di
mov di, dx
dec cx
B:
mul ax
; loop b
mov bx, ax
; print "y^z="
; call print_num
; printn
pop ax
sub ax, bx
; print "R2="
; call print_num
; printn
lea dx, [pkey]
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
;ends
;define_scan_num
;define_print_num
;define_print_num_uns
;end start ; set entry point and stop the assembler.