Ввод информации с клавиатуры:
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. Ввод строки, отличается только тем, что такое сравнение надо проводить с каждым элементом, т.е. надо организовать цикл и обращение к каждому элементу. Рассмотрим позднее.
Вывод информации на экран
Название флага | Номер бита в 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
Пример 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