Смекни!
smekni.com

Программирование контроллера приоритетных прерываний (стр. 3 из 8)

Ввод информации с клавиатуры:

1. Ввод символа с клавиатуры, один ASCII код находится в dl. Заранее не известно, что это за число от 0 до 9 или от а до f.

Cmpdl, 040h

Jbm1 ; если ASCII код меньше 40h значит ввели цифру от 0 до 9,

;переходим на метку m1

Cmpdl, 047h ; иначе ввели букву, заглавную или маленькую?

Jbm2 ;если ввели заглавную, переходим на m2, иначе выполняем

;дальше по программе

subdl, 057h ;в dl получаем из символов число a..fh

jmpm3 ;переходим на m3 чтобы не выполнять лишних вычислений

m2: subdl, 037h ;в dl получаем из символов число a..fh

jmpm3

m1: subdl, 030h ;в dl получаем из символов число 0..9 h

m3:

Далее приведен оптимизированный код преобразования числа из ASCII кодов. Подумайте в чем разница.

Cmpdl,040h

Jbm1

Cmpdl,047h

Jb m2

Sub dl, 020h

m2: sub dl, 07h

m1: sub dl, 030h

2. Ввод строки, отличается только тем, что такое сравнение надо проводить с каждым элементом, т.е. надо организовать цикл и обращение к каждому элементу. Рассмотрим позднее.

Вывод информации на экран

1. Предположим что, число, которое мы хотим вывести, находится в регистре bl. Вывод символа осуществляется из регистра dl, 02 функция INT 21H. Число может быть одно или двузначное, например 7h или 5Fh. Для универсальности программы будем считать, что надо вывести двузначное число. А для этого надо получить отдельно десятки и единицы, и получить для них два ASCII кода.

;двузначное число которое хотим вывести находится в bl

movdl, bl ; помещаем число в регистр dl

;сдвигаем содержимое dl на 4 бита вправо, чтобы получить отдельно десятки

shrdl, 4

andbl, 0fh ;получаем отдельно единицы

cmpdl, 0ah ;сравниваем dl с ah

jbm1 ;если меньше переходим на m1

add dl, 07h

m1: add dl, 30h

mov ah, 02h

int 21h

mov dl, bl

cmpdl, 0ah ;сравниваем dl с ah

jb m2

add dl, 07h

m2: add dl, 30h

int 21h

Попробуйте сами разобраться в приведенном кусочке кода.

Команды передачи управления

По принципу действия, команды микропроцессора, обеспечивающие организацию переходов в программе, можно разделить на три группы:

1. Команды безусловной передачи управления:

- команда безусловного перехода; jmp

- вызова процедуры и возврата из процедуры; call, ret

- вызова программных прерываний и возврата из программных прерываний. Int, iret

2. Команды условной передачи управления:

- команды перехода по результату команды сравнения cmp;

- команды перехода по состоянию определенного флага;

- команды перехода по содержимому регистра ecx/cx.

3. Команды управления циклом:

- команда организации цикла со счетчиком ecx/cx;

- команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

jmp адрес_перехода - безусловный переход без сохранения информации о точке возврата. Аналог goto.

Условные переходы

Команды условного перехода имеют одинаковый синтаксис:

jcc метка_перехода

Мнемокод всех команд начинается с “j” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой. Что касается операнда метка_перехода, то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается.

Для того чтобы принять решение о том, куда будет передано управление командой условного перехода, предварительно должно быть сформировано условие, на основании которого и будет приниматься решение о передаче управления. Источниками такого условия могут быть:

- любая команда, изменяющая состояние арифметических флагов;

- команда сравнения cmp, сравнивающая значения двух операндов;

- состояние регистра ecx/cx.

jcxz метка_перехода (JumpifcxisZero) — переход, если cx ноль;

jecxz метка_перехода (JumpEqualecxZero) — переход, если ecx ноль.

Условные переходы по содержимому флагов

Название флага Номер бита в eflags/flag Команда условного перехода Значение флага для осуществления перехода
Флаг переноса cf 1 jc cf = 1
Флаг четности pf 2 jp pf = 1
Флаг нуля zf 6 jz zf = 1
Флаг знака sf 7 js sf = 1
Флаг переполнения of 11 jo of = 1
Флаг переноса cf 1 jnc cf = 0
Флаг четности pf 2 jnp pf = 0
Флаг нуля zf 6 jnz zf = 0
Флаг знака sf 7 jns sf = 0
Флаг переполнения of 11 jno of = 0

Пример 9. Определите, равны ли два числа вводимые пользователем с клавиатуры. Определить равенство чисел можно используя вычитание, если разность исследуемых чисел равна 0, то они равны.

model small

.stack 100h

.data

s1 db 'числаравны$'

s2 db 'числа не равны$'

.code

start:

mov ax,@data

movds,ax

movah,01h

int 21h ;ввели первое число

movdl,al ;посылаем в dl первое число

int 21h ;ввели второе число

subal,dl ;сравнили числа

jnzm1 ;если получили не 0 результат, то на метку m1

movdx, offsets1 ;иначе выводим строку s1, о том что числа равны.

jmpm2

m1: movdx, offsets2 ;числа не равны, выводим строку s2

m2: movah,09h

int 21h ;вывод информационную строку

mov ax,4c00h

int 21h

end start

Команда сравнения cmp

cmp операнд_1,операнд_2 - сравнивает два операнда и по результатам сравнения устанавливает флаги. Команда сравнения cmp имеет интересный принцип работы. Он абсолютно такой же, как и у команды вычитания sub. Единственное, чего она не делает — это запись результата вычитания на место первого операнда.

Алгоритм работы:

-выполнить вычитание (операнд1-операнд2);

-в зависимости от результата установить флаги, операнд1 и операнд2 не изменять (то есть результат не запоминать).

Условные переходы после команд сравнения

Типы операндов Мнемокод команды условного перехода Критерий условного перехода Значения флагов для осществления перехода
Любые je операнд_1 = операнд_2 zf = 1
Любые jne операнд_1<>операнд_2 zf = 0
Со знаком jl/jnge операнд_1 < операнд_2 sf <> of
Со знаком jle/jng операнд_1 <= операнд_2 sf <> of or zf = 1
Со знаком jg/jnle операнд_1 > операнд_2 sf = of and zf = 0
Со знаком jge/jnl операнд_1 => операнд_2 sf = of
Без знака jb/jnae операнд_1 < операнд_2 cf = 1
Без знака jbe/jna операнд_1 <= операнд_2 cf = 1 or zf=1
Без знака ja/jnbe операнд_1 > операнд_2 cf = 0 and zf = 0
Без знака jae/jnb операнд_1 => операнд_2 cf = 0

Пример 10. Определите, равны ли два числа вводимые пользователем с клавиатуры.

model small

.stack 100h

.data

s1 db 'числаравны$'

s2 db 'числа не равны$'

.code

start:

mov ax,@data

movds,ax

movah,01h

int 21h ;ввели первое число

mov dl,al

mov ah,01h

int 21h ;ввели второе число

cmpal,dl ;сравнили числа

jne m1

mov dx, offset s1

jmp m2

m1: mov dx, offset s2

m2: movah,09h

int 21h ;вывод информационную строку

mov ax,4c00h

int 21h

end start

Пример 11. Даны три числа, найти среди них максимальное.

model small

.stack 100h

.data

s1 db 'максимальноечисло',10,13,'$'

x1 db 34

x2 db 56

x3 db 45

.code

start:

mov ax,@data

mov ds,ax

mov dx, offset s1

mov ah,09h

int 21h ;вывод информационную строку

;находим максимальное число

movdl,x1 ;dl:=x1

cmpdl,x2 ;сравниваем х1 и х2

jam1 ;если х1>х2, то на m1

movdl,x2 ;иначе dl:=x2

m1: cmpdl,x3 ;сравниваем dl и х2

jam2 ;если dl>х3 то на m2

movdl,x3

;в dl находится самый максимальный элемент

m2: movah,02h

int 21h ;выводим максимальный элемент

mov ax,4c00h

int 21h

end start

Организация циклов

loop метка_перехода (Loop) — повторить цикл

Работа команды заключается в выполнении следующих действий:

- декремента регистра ecx/cx;

- сравнения регистра ecx/cx с нулем:

- если (ecx/cx) > 0, то управление передается на метку перехода;

- если (ecx/cx) = 0, то управление передается на следующую после loop команду

Организация цикла:

movcx, количество циклов

м1: тело цикла

loopm1

loope/loopz метка_перехода (Loop till cx <> 0 or Zero Flag = 0) — повторить цикл, пока cx <> 0 или zf = 0.

loopne/loopnz метка_перехода (Loop till cx <> 0 or Not Zero flag=0) — повторить цикл пока cx <> 0 или zf = 1

Недостаток команд организации цикла loop, loope/loopz и loopne/loopnz в том, что они реализуют только короткие переходы (от –128 до +127 байт).

Организация вложенных циклов:

movcх,n ; в сх заносим количество итераций внешнего цикла

m1:

pushcx

movcx,n1; в сх заносим количество итераций внутреннего цикла

m2:

тело внутреннего цикла

loopm2

popcx

loopm1

Пример 12. Напишите программу подсчета у=1+2+3+…+n, n не более 10000.

model small

.stack 100h

.data

yb dd ?

ym dw ?

s1 db 'введите n',10,13,'$'

.code

start:

mov ax,@data

mov ds,ax

mov dx, offset s1

mov ah,09h

int 21h