- •Введение
- •1. Особенности персонального компьютера
- •1.1. Оперативная память
- •1.2. Регистры
- •1.3. Представление данных
- •1.4. Представление команд
- •2. Язык ассемблера. Начальные сведения
- •2.1. Лексемы
- •2.2. Предложения
- •2.3. Директивы определения данных
- •2.4. Директивы эквивалентности и присваивания
- •2.5. Выражения
- •3. Пересылки. Арифметические команды
- •3.1. Обозначения операторов команд
- •3.2. Команды пересылки
- •3.3. Команды сложения и вычитания
- •3.4. Команды умножения и деления
- •3.5. Изменение размера числа
- •3.6. Примеры
- •3.7. Лабораторная работа № 1
- •4. Переходы. Циклы
- •4.1. Безусловный переход
- •4.2. Команды сравнения и условного перехода
- •4.3. Команды управления циклом
- •4.4. Вспомогательные операции ввода-вывода
- •4.5. Массивы
- •4.6. Лабораторная работа № 2
- •5. Программные сегменты
- •5.1. Сегментирование адресов в пк
- •5.2. Программные сегменты
- •5.3. Начальная загрузка сегментных регистров
- •5.4. Структура программы
- •6. Стек
- •6.1. Стек и сегмент стека
- •6.2. Стековые команды
- •6.3. Приемы работы со стеком
- •7. Процедуры
- •7.1. Дальние переходы
- •7.2. Подпрограммы-процедуры
- •7.3. Передача параметров через регистры
- •7.4. Передача параметров через стек
- •7.5. Локальные данные процедур
- •7.6. Лабораторная работа № 3
- •8. Ввод и вывод данных
- •8.1. Реализация основных операций ввода-вывода
- •8.2. Операции ввода-вывода
- •8.3. Пример структуры программы
- •Заключение
- •Библиографический список
- •Оглавление
- •Учебное издание
- •394026 Воронеж, Московский просп., 14
3.6. Примеры
В этом разделе рассматриваются примеры использования раньше описанных команд ПК и средств языка ассемблера, что описаны ранее, и приводятся их решения с пояснениями.
Пример 1
X DD ?
Требуется переставить местами оба слова двойного слова X.
Решение
Какие именно команды здесь нужны, определить несложно. Проблема здесь в другом - в том, что в этих командах нельзя непосредственно указывать адреса X и Х+2. Например, при трансляции команды
MOV АХ,Х
ассемблер зафиксирует ошибку, т. к. в команде MOV можно указывать операнды только типов BYTE и WORD, а здесь указан операнд X типа DWORD. Чтобы не было такой ошибки, надо явно указать ассемблеру, чтобы он рассматривал X не как имя двойного слова, а как имя слова, для чего следует применить оператор PTR. С учетом сказанного задача решается так:
MOV AX,WORD PTR X ;АХ:=Xлев
XCHG AX,WORD PTR X+2 ;АХ:=Xправ, Xправ:=Xлев
MOV WORD PTR X,AX ;Xлев:=прежнее значение
; Xправ
Воспользуемся этим примером и рассмотрим один из приемов сокращения записи команд. Как видно, в приведенных выше командах несколько раз используется конструкция WORD PTR. Так вот, чтобы многократно не выписывать эту достаточно длинную конструкцию, можно с помощью директивы EQU обозначить ее коротким именем, а затем использовать это имя. В результате получим более короткий вариант записи команд:
WP EQU WORD PTR
MOV AX, WP X
XCHG AX, WP X+2
MOV WP X,AX
Пример 2
W DW 1234h
Определить значения регистров АХ и ВХ после выполнения команд
MOV AX,W
MOV BH,BYTE PTR W
MOV BL,BYTE PTR W+1
Решение
Ответ здесь такой: AX=1234h, BX=3412h.
Казалось бы значения регистров АХ и ВХ должны совпадать, а они различаются. Почему? Следует напомнить, что в памяти ПК слова хранятся в «перевернутом» виде; в нашем случае в байте с адресом W находится величина 34h, а в байте с адресом W+1 - величина 12h. Поэтому вторая из приведенных команд записывает в старшую часть регистра ВХ (в ВН) младшие цифры числа W, а в третьей команде в младшую часть регистра ВХ (в BL) записываются старшие цифры числа, и потому в регистре ВХ число W оказывается в «перевернутом» виде.
Во всех же командах, работающих со словами как с единым целым, такая особенность представления слов в памяти учитывается, и эти команды «переворачивают» слова автоматически.
Поэтому первая из команд сама «перевернет» слово W и запишет его в регистр АХ в нормальном, не перевернутом виде. При использовании таких команд можно забыть о «перевернутом» представлении слов в памяти, но если слово обрабатывается по частям (по байтам), тогда автоматического «переворачивания» нет и следует помнить о «перевернутом» представлении.
Пример 3
Пусть X – байтовая переменная, значение которой трактуется как знаковое число, a Y – переменная размером в слово. Вычислить Y=X*X*X при условии, что результат имеет размер слова.
Решение
При использовании арифметических команд ПК надо внимательно следить за размерами операндов, за правильностью расширения чисел (со знаком или без), а если используются команды умножения, деления и расширения со знаком, то надо следить и за тем, чтобы их операнды находились в нужных регистрах.
В нашем примере мы сначала умножим байт X на себя. Поскольку один из операндов команды IMUL должен находиться в регистре AL, то прежде всего записываем X в этот регистр. Получив в регистре АХ произведение Х*Х, мы должны умножить его на байт X. Поскольку в ПК нельзя умножать слово на байт, то приходится расширять байт X до слова, причем расширять со знаком, для чего воспользуемся командой CBW. Поскольку эта команда использует регистр АХ, то предварительно этот регистр надо освободить. Произведение Х*Х*Х уже будет иметь размер двойного слова и будет находиться в регистрах DX и АХ. Однако, согласно условию задачи, для нашего произведения достаточно лишь слова, поэтому старшую часть произведения, т. е. содержимое регистра DX, можно проигнорировать.
С учетом всех замечаний получаем такие команды:
MOV AL, X
IMUL AL ; АХ:-Х*Х (можно: IMOL X)
MOV ВХ,АХ ; спасти АХ
MOV AL, X
CBW ; АХ:=Х как слово
IMUL ВХ ; (DX,AX):=X*X*X
; (DX можно не учитывать)
MOV Y,AX
Пример 4
N DB ?
D DB 3 DUP(?)
Рассматривая N как беззнаковое число (от 0 до 255), записать в массив D цифры (как символы) из десятичной записи этого числа: в байт D - левую цифру, в байт D+1 – среднюю цифру, в байт D+2 - правую цифру.
Решение
Пусть a, b и с – десятичные цифры числа N: N=abc. Для получения правой цифры с надо взять остаток от деления N на 10. Неполное же частное от такого деления – это число ab, поэтому если его разделить на 10, то неполное частное даст цифру а, а остаток – цифру. Следует отметить, что непосредственно делить байт N на 10 нельзя, т. к. в ПК нет команды деления бантов, поэтому предварительно надо расширить N до слова, причем расширить без знака.
Полученные величины a, b и с – это цифры как числа (от 0 до 9). Чтобы получить эти цифры как символы (от '0' от '9'), к ним надо прибавить код символа '0', т. к. в используемых в ПК системах кодировки справедливо следующее соотношение: код(0=код('0') + i, где i – цифра.
MOV BL,10 ;делитель
MOV AL, N
MOV АН, 0 ;AX:=N как слово
DIV BL ;АН:=с, AL:=ab
ADD АН, '0' ;правая цифра как символ
MOV D+2, AH ;запомнить с
MOV АН, 0 ;АХ:=аb как слово
DIV BL ;AH:=b, AL:=a (как числа)
ADD AX, '00' ;обе цифра как символы
;(AH:-b+'0', AL:-a+'0')
MOV D+1, АН ;запомнить b
MOV D, AL ;запомнить а
Пример 5
X DD ?
Y DW ?
Z DW ?,?,?
Вычислить Z=X*Y в предположении, что числа X и Y беззнаковые и что их произведение записывается в тройном слове Z в «перевернутом» виде: младшие (правые) цифры (Zмл) - в слове с адресом Z, средние цифры (Zcp) - в слове с адресом Z+2, старшие цифры (Zcт) - в слове с адресом Z+4.
Решение
Поскольку в ПК нет команды умножения двойного слова на слово, такое умножение приходится реализовывать нам самим с помощью имеющихся команд. Для этого будем рассматривать двойное слово X как два слова Хст и Хмл и будем выполнять умножение по следующей схеме, приведенной на рис. 23.
Рис. 23. Схема умножения двойного слова X на слово Y
Отметим, что перед адресами Z, Z+2 и Z+4 не надо указывать конструкцию WORD PTR, т. к. имя Z согласно описанию уже имеет тип WORD, а вот перед адресами X и Х+2 ее надо ставить.
С учетом всего сказанного получается такое решение задачи:
WP EQU WORD PTR
MOV AX,WP X ;АХ:=Хмл
MUL Y ;(DX,AX):=Xмл*Y
MOV Z,AX ;Zмл
MOV BX,DX ;спасти старшую часть Хмл*Y
MOV AX,WP X+2 ;АХ:=Хст
MUL Y ;(DX,AX):=Xст*Y
ADD AX,BX ;AX:=(Xст*Y)мл+(Xмл*Y)ст,
;СF = перенос
MOV Z+2,AX ;Zср
ADC DX,0 ;DX:=(Xст*Y)ст+CF
MOV Z+4,DX ;Zст