Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архитектура ЭВМ и систем. Лабораторная работа. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
Пример:
Mov ax,100H ;ax=256 Add ax,30H ;ax=304
Также существуют разновидности этих команд: сложение с пе­реносом ADC и вычитание с заемом SBB. Первая учитывает перенос из старшего разряда, который произошел в результате сложения. Вторая учитывает заем в старший разряд, который имел место при вычитании. Факт заема или переноса определяется значением флаж­ка переноса CF=1.
Пример использования команды SBB при вычитании двойных слов
и команды ADC при сложении:
Mov dx,0000H Mov ax,0000H Sub ax,0001H ;ax = 0FFFFH (-1), CF = 1 Sbb dx,0000H ;dx = 0FFFFH, dx:ax = -1
Mov ax,0FFFFH Mov dx,0000H Add ax,0001H ;ax = 0000H , CF=1 Adc dx,0000H ;dx = 0001H, dx:ax = 10000H
Возникновение ошибок при операциях сложения и вычитания
При выполнении арифметических операций необходимо сле­дить за тем, чтобы результат не получился неправильным.
При сложении флаг переноса (CF) устанавливается, когда про­исходит перенос из старшего бита. Флаг переполнения (OF) уста­навливается, когда возникает перенос в старший бит без переноса из старшего бита, либо когда происходит перенос из старшего бита без переноса в
старший бит.
Если при сложении двух беззнаковых чисел возникает перенос, результат получается неправильный.
Беззнаковое Знаковое Флаги
FFh +255
+
1 1 OF=0
01h 00h 0 0
неправильно
-1 CF=1
+
правильно
41
Если при сложении двух знаковых значений возникает пере­полнение, тогда имеет место ошибка.
Беззнаковое Знаковое Флаги
7Fh +127
+
1 1 OF=1
01h 80h 128 -128
правильно
127 CF=0
+
неправильно
Возможна ситуация, когда одновременно возникает и перенос, и переполнение. В этом случае как для знаковых операндов, так и для беззнаковых операций результат неверный.
Беззнаковое Знаковое Флаги
80
+
128
+
-128 CF=1
-
h 80h
128 -128 OF=1
00h 0 0
неправильно неправильно
При вычитании флаг переноса устанавливается, когда происхо­дит заем в старший бит. Флаг переполнения устанавливается, когда происходит заем в старший бит без заема из старшего бита или при заеме из старшего бита без заема в старший бит.
Если при вычитании двух знаковых значений возникает пере­полнение, тогда результат получается неправильным.
Беззнаковое Знаковое Флаги
_90h _144 _-112 CF=0
20h
32 32 OF=1
70h 112 -112
правильно
неправильно
42
Если при вычитании двух беззнаковых чисел возникает пере­нос, результат также неправильный.
Беззнаковое Знаковое Флаги
_0Fh _15 _15 CF=1
16 16 OF=0
10h FFh 255 -1
неправильно правильно
Возможна ситуация, когда одновременно возникает и перенос, и переполнение. В этом случае как для знаковых операндов, так и для беззнаковых результат неверный.
Беззнаковое Знаковое Флаги
_70h _112 _112 CF=1
128 -128 OF=1
80h F0h 240 -16
неправильно правильно
Команды умножения и деления
Мнемоники команд умножения и деления, соответственно, для беззнаковых значений: MUL и DIV, для знаковых: IMUL, IDIV. Формат их записи следующий:
DIV src IDIV src MUL src IMUL src,
где src – память или регистр размером 8 или 16 бит. При умно­жении на байт множимое находится в регистре AL, результат поме­щается в регистр AX. При умножении на слово первый операнд на­ходится
в AX, результат получается в DX:AX. При делении на байт
делимое находится в регистре AX. Частное помещается в регистр
AL, остатокв AH. При делении на слово делимое находится в DX:AX, частное помещается в AX, остаток от деленияв DX.
43
Переполнение при делении
Если частное имеет значение больше, чем возможное для по­мещения в регистр, тогда о переполнении сигнализирует исключе­ние с номером вектора 0 (деление на нуль). Чтобы избежать этого, рекомендуется проверять, не больше ли старшая половина делимого, чем частное (при делении на байт – AH, для деления на слово – DX). Если да,
тогда результат операции получится слишком большим, чтобы можно было использовать стандартную команду деления. В этом случае можно использовать различные алгоритмы определения частного, например с помощью вычитания.
Изменение знака
Для изменения знака используется команда NEG. Она инверти­рует значения битов и прибавляет 1 для получения значения проти­воположного знака. Ее операндом может служить
как регистр, так и ячейка памяти. Пример аналогичной этой команде последовательно­сти инструкций:
NOT AX
ADD AX,1
Команды сдвига
Команды SHL, SHR и SAR осуществляют сдвиг первого опе­ранда, который может находиться в памяти или регистре на количе­ство битов, задаваемое вторым операндом. Размер сдвига может быть определен непосредственно в виде константы или в виде пере­менной величины в регистре CL:
SHL AL,CL ;сдвиг AL на CL бит влево
SHR CX,1 ;сдвиг CX на 1 бит вправо
Сдвиг
влево на один бит эквивалентен умножению на 2, вправо – делению. Команда SHL осуществляет умножение, SHR – беззнако­вое деление, SAR – знаковое. Последний выдвинутый бит помеща­ется во флажок CF.
Флаг OF определен только при сдвиге на 1 разряд.
44
MOV AL,0FFH ;AL=0FFH CF=0 OF=0 SHR AL,1 ;AL=7FH CF=1 OF=1 SHL AL,1 ;AL=0FEH CF=0 0F=1 SAR AL,1 ;AL=0FFH CF=0 OF=0
Команды циклического сдвига имеют тот же формат операндов, что и обычного. ROR осуществляет сдвиг вправо, помещая последо­вательно выдвигаемый младший бит в старший. Во флажке CF оста­ется значение последнего выдвинутого разряда. ROL производит сдвиг влево. RCL и RCR осуществляют сдвиг соответственно влево и вправо. При этом каждый выдвигаемый бит помещается в CF, а содержимое CF –
в освободившийся разряд.
MOV AL,81H ;AL=81H CF=0 OF=0 ROL AL,1 ;AL=3 CF=1 OF=1 RCL AL,1 ;AL=7 CF=0 0F=0 ROR AL,3 ;AL=0E0H CF=1 OF=0
Перевод из десятичного формата в двоичный и обратно
Пользователь вводит и принимает информацию в символьном виде. Таким образом, в интерактивной вычислительной программе должны быть предусмотрены процедуры перевода чисел между двоичным форматом для ЭВМ и десятичным – для человека. Каж­дому символу, вводимому с клавиатуры или отображаемому
на эк­ране, соответствует некоторый код размером 1 байт. Для символов, обозначающих цифры от "0" до "9", они имеют значение от 30H до 39H. Строка "1234" будет иметь в шестнадцатеричном формате представление 31323334 и занимать четыре байта.
Для перевода в двоичный формат можно использовать процеду­ру, которая удаляет старшие тройки у ASCII-кодов и вычисляет, на­пример для
вышеприведенной строки "1234", двоичное значение по
формуле X = ((1*10+2)*10+3)*10+4.
Для обратного перевода необходимо разложить значение Х на остатки от деления на 10: (((X mod 10) mod 10) mod 10) mod 10, при­бавив потом к каждому 30Н.
45
Функции ввода-вывода MS-DOS
При выполнении заданий для ввода с клавиатуры и вывода на экран можно использовать следующие функции MS-DOS, обраще­ние к которым осуществляется через прерывание 21H.
1. Печать строки. AH содержит значение 09H. DS:DX указывает
на выводимую строку, которая должна оканчиваться знаком '$'. Доллар не печатается. Для форматированного вывода можно ис­пользовать коды 0DH – возврат каретки, 0AH –
перевод строки,
09H – табуляция.
2. Ввод с клавиатуры с буферизацией. AH = 0AH. DS:DX указы-
ваем на буфер, первый байт которого содержит максимальное число символов, которое пользователь может ввести. Это значе­ние должно учитывать код 0DH завершающей ввод клавиши En­ter. Во второй байт помещается количество введенных пользова­телем символов без учета символа 0DH. Начиная с третьего бай­та
размещается вводимая строка.
Пример
Приводимая ниже программа иллюстрирует использование процедур ввода и вывода, перевода в десятичный и двоичный фор­маты. При запуске она просит пользователя ввести два числа, а за­тем вычисляет и выводит их сумму.
.8086 dsg segment para
;выводимые сообщения msgX db 13,10,'Введите Х:$' msgY db 13,10,'Введите Y:$' msgXY db 13,10,'X + Y = $' ;буфер для ввода maxlen db 5 ;максимальное
число
вводимых символов
strlen db 0 ;сколько символов
введено
buf db 5 dup (' ') ;буфер для ввода bufend equ $-1 ;последний байт
буфера
46
dsg ends csg segment para assume cs:csg, ds:dsg start: mov ax,dsg mov ds,ax ;установим сегментный
регистр данных
lea dx,msgX ;выведем приглашение
на ввод Х call print lea dx,maxlen ;введем Х call input
xor bh,bh mov bl,[strlen] ;длина введенной
строки mov byte ptr [buf+bx],'$' lea di,buf call ToBinary ;переведем Х в
двоичный формат
push ax ;сохраним Х в стеке
lea dx,msgY ;выведем приглашение
на ввод Y call print lea dx,maxlen ;введем Y call input
xor bh,bh mov bl,[strlen] ;длина введенной
строки mov byte ptr [buf+bx],'$' lea di,buf call ToBinary ;переведем Y в
двоичный формат
pop bx ;извлечем Х из
стека
add ax,bx ;вычислим сумму Х+Y
47
lea di,bufend ;di->конец буфера call ToAscii ;вызовем процедуру
перевода
;в десятичный формат mov ah,9 ;выведем сумму на
экран
lea dx,msgXY int 21H mov ah,9 mov dx,di int 21H
mov ax,4C00H ;выйдем из программы int 21H
;подпрограмма вывода строки на экран ;ds:dx содержит указатель на строку, заканчиваю­щуюся символом '$' print proc near
mov ah,9 int 21H ret
print endp ;подпрограмма ввода строки c клавиатуры ;ds:dx содержит указатель на подготовленный буфер input proc near
mov ah,0AH
int 21H
ret input endp ;подпрограмма перевода из десятичного формата в двоичный ;ds:di -- указатель на первую цифру числа в десятичном формате, ;оканчивающееся '$' ;при возврате в ax содержится переведенное число ToBinary proc near
xor ax,ax ;сначала сумма равна нулю
xor bh,bh
mov cx,10 ;основание системы
счисления -- 10
48
l1:
mov bl,[di] ;bl = очередной разряд
cmp bl,'$' ;конец строки?
je l2
inc di ;передвинем указатель
вперед mul cx ;умножим сумму на 10 and bl,0FH ;уберем старшую
половину ascii-кода add ax,bx ;прибавим значение
очередного разряда jmp short l1
l2:
ret
ToBinary endp ;подпрограмма перевода из двоичного формата в де­сятичный ;ax -- переводимое число ;ds:di -- указатель на конец буфера, в который помещается строка, ;оканчивающаяся '$' ;при возврате ds:di указывает на начало
строки
ToAscii proc near
mov cx,10 ;делительоснование
системы счисления ;поместим в конец
буфера символ конца
;строки mov byte ptr [di],'$'
l3:
xor dx,dx ;обнулим dx div cx or dl,30H ;преобразуем цифру
в ее ascii-код dec di ;уменьшим указатель mov [di],dl ;сохраним в буфере
очередной разряд
числа
cmp ax,0 ;все число разделили
(ax равен 0)?
49
jne l3 ret ;выход из подпрограммы
ToAscii endp csg ends ssg segment stack db 1024 dup(?) ssg ends end start
Задания для выполнения
Для того чтобы выполнить следующие задания, необходимо
модифицировать процедуры перевода форматов чисел из примера программы так, чтобы они обрабатывали знаковые числа.
Задание № 1. Составить программу, вычисляющую значение
выражения и выводящую результат на экран.
Варианты задания:
1. 90 / 35 – (45 * 64 + 32 * 85) / 3
2. 10 – 20 * 30 + 40
3. (100 * 3 + 40*25 – 64 / 8 ) mod 18
4. (54 / 32 – 48 ) * 36 + 70 mod 9
5. (( 82 – 177 ) * 6 + 6) / 6
6. (340 + 640 – 32 * 400) / 100
7. (1024 + 2048 – 400) / (–256) * 123
8. 777 – (888 mod 79) * 300
9. 10 + 20 * (30 – 40 * 64 + 50)
10. – (20 * 3 + 40 / 6) mod 67
11. (34 + 48 / 8) – (54 – 36) * 4
12. (70 + 80 + 90 – 100 – 34 * 5 / 6) * (–525)
13. 5 * 40 / 80 – 18 * 700
14. 100 + 24 * (36 – 654)
15. 700 + 200 * 4 – 12000 mod 3456
16. (800 * 4 – 90 * 5) / ((–100) mod 6)
17. 18 * 360 – 400 * 34 + 80 / 23 – 44 mod 12
18. –340 + 67 – 80 * (34 / 25 –46 mod 18)
19. –10 * (18 + 7 * (4 + 800))
20. (14 + 7 * 36 – 18 * 1000) /102) mod 36
50
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]