Контрольная работа №1
Архитектура ЭВМ
Целью данной лабораторной работы является знакомство с устройством вычислительной машины и взаимодействие программиста с аппаратной частью ЭВМ посредством программного обеспечения.
Работа состоит из двух частей. В первой части необходимо описать одно из устройств компьютера, указанное преподавателем. Во второй части нужно написать программу на языке Ассемблер используя программу Debug , которая должна выполнять задачу, указанную преподавателем. Программа должна быть распечатана, иметь комментарии в каждой строке. Кроме того, нужно кратко описать устройства, которые используются в программе. Написанная программа должна быть сохранена на дискете и при защите работы должна быть загружена и запущена студентом на выполнение.
Для выполнения данной работы необходимо:
1. Запустить Debug через окно «Выполнить»
2. Войти в режим ассемблирования, набрав а после приглашения
3. Запустить программу на выполнение G=100
4. Сохранить программу, используя команды N, R,W
5. Уметь загрузить программу с дискеты командами N, L
Описание команд Debug дано в файле PAGE10. Debug (отладчик) входит в большинство операционных систем DOS иWindows. Для изучения команд процессора, прерываний DOS и BIOS портов ввода\вывода смотри HELP1.
4. а) Описать адресацию и работу параллельного порта компьютера
б) Провести сравнение чисел X иY.Если X >Y , вывести на экран 0, если X <Y,
вывести на экран 1.
Написание программы
в Debug и
сохранение программы на диск.
Для создания данной программы будем использовать две функции DOS: функцию вывода строки на экран и функцию ввода с клавиатуры.
О функциях DOS
Функции DOS представляют собой неорганизованную кучу средств управления файлами, устройствами, памятью и процессами, доступных любой программе, которая способна установить регистры и вызвать программное прерывание.
Чтобы обратиться к функции DOS:
- поместить номер функции DOS в регистр AH (если есть подфункции, то номер подфункции
обычно помещается в AL)
- загрузить остальные регистры согласно описанию функции
- подготовить необходимые буферы, строки ASCII и управляющие блоки
- вызвать прерывание INT 21H
- проверить индикатор ошибки, возвращенный DOS (флаг переноса)
DOS не изменяет значений регистров, исключая случаи, когда результирующие данные возвращаются через регистры. В процессе развития DOS новые версии остаются (в целом) совместимыми с более ранними версиями.
1). Функция ввода с клавиатуры
вход: AH = 02h
выход:
Данная функция считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо).
2). Функция вывода строки на дисплей
вход: AH = 09h
DS:DX = адрес строки, заканчивающейся символом ‘$’
выход: нет
Описание :
Строка, исключая завершающий её символ ‘$’, посылается на стандартный вывод.
Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 0Dh и 0Ah).
3). Завершение программы
Вызвать прерывание DOS Int 20h
Подготовка данных
(строк) для вывода на экран
Разместим в памяти строки диалога с пользователем для наглядности программы. Для перехода на новую строку будем вводить перед каждой строкой по два байта 0d 0a (см. выше).
Запускаем Debug и записываем в память строки. Запоминаем адреса начала строк, для последующего обращения к ним из программы:
рис.1
На рис.1 видно, что сначала мы ввели в память два байта 0D и 0A в адреса 13E2:0200 и 13E2:0201 соответственно, а далее с адреса 13E2:0202 расположили первую строку программы "Вариант №4…". Последний байт этой строки символ $, код которого 24h, расположился по адресу 13E2:0243. Поэтому продолжаем ввод оставшихся строк с адреса 13E2:0244. После введения каждой строки командой "damp"= d просматриваем дамп памяти для определения адреса ввода последующей строки.
Листинг программы
mov ax, 900 `подготавливаем функцию вывода строки на
экран, AH = 09h
mov dx, 200 `в регистр dx вносим адрес выводимой строки "Вариант
№4……"
int
21 `вызываем прерывание DOS для выполнения функции вывода строки на экран
mov dx, 244 `в регистр dx вносим
адрес строки "Введите число Х="
int
21 `вызываем прерывание DOS для выполнения функции вывода строки на экран
mov ax, 100 `подготавливаем функцию ввода символа с
клавиатуры, AH = 01h
int
21 `вызываем прерывание DOS для выполнения функции
mov cx, ax `сохраним
(скопируем) значение регистра AX (
` регистре
CX для
последующего использования (сравнения)
mov ax, 900 `опять готовим функцию вывода на экран, AH = 09h
mov dx, 257 `адрес строки "Введите число Y ="
int 21
`вызываем прерывание DOS для
выполнения функции вывода строки на экран
mov ax, 100 `готовим функцию ввода символа, AH = 01h
int
21 `выполняем эту функцию:
программа ожидает ввода символа с клавиатуры
mov bx, ax `копируем
значение регистра ax (
mov ax, 900 `установим заранее функцию вывода на экран,
AH = 09h
cmp cx, bx
`сравниваем значения регистров CX и BX, в которые мы сохранили числа X и Y
JG ds:133 `если
число Х (т.е.его 16–ричный код) больше числа Y (...), то переходим к
` адресу 133, где
запрограммирован вывод соответствующей строки на экран
JL ds:13A `если
число Х (т.е.его 16–ричный код) меньше числа Y (...), то переходим к
` адресу 13A, где запрограммирован вывод соответствующей строки на
экран
mov dx, 288 `в dx вносим
адрес строки о равенстве чисел X и Y (переходы jg и jl не совершились)
int
21 `прерывание DOS, вывод строки на экран
int
20 `завершение программы
mov dx, 26a `в dx
вносим адрес строки "X >
Y" (сюда перейдёт по команде jg)
int
21 `прерывание DOS, вывод строки на экран
int
20 `завершение программы
mov dx, 279 `в dx вносим
адрес строки "X < Y" (сюда
перейдёт по команде jl)
int
21 `прерывание DOS, вывод строки на экран
int
20 `завершение программы
Ввод программы в Debug начинаем командой "assembler" – a. Программа записывается с адреса 100 (если нет, то ввести команду a100). Сегментный регистр здесь DS = 13E2 (не существенно). В процессе программирования мы его
не изменяем, поэтому адресацию производим лишь через регистр DX:
Запись программы на диск
Для записи программы на диск необходимо знать её размер в байтах, и это значение необходимо внести в регистр CX. Последний байт внесённый до этого нами в область данных имеет адрес 296 (см. выше). Это значение и будет размером программы. Вводим это число в регистр CX:
Далее необходимо командой "name"– n ввести имя программы (придумать) и командой "write"– w произвести запись программы в файл:
Теперь чтобы загрузить эту программу в Debug надо ввести её имя командой "name"– n, и загрузить командой "load" – L (файл программы должен находиться в каталоге программы debug):
Для запуска программы вводим команду g:
В данной программе сравниваются числа от 0 до 9. Анализ правильности ввода (что введено именно число, а не какая–нибудь буква) не производится. Данную проверку возможно было бы производить по анализу кодов введённых символов. То есть, если коды введённых символов выходят за рамки определённого диапазона (30h – 39h), то программа возвращается к вводу числа X или Y.
Примечания по использованным в программе командам
1). Команда MOV
(пересылка данных)
Команда MOV замещает первый операнд (приемник) вторым (источником). При этом исходное значение первого операнда теряется. В зависимости от описания операндов пересылается слово или байт. Если операнды описаны по-разному или режим адресации не позволяет однозначно определить размер операнда, для уточнения размера передаваемых данных в команду следует включить один из атрибутных операторов byte ptr или word ptr. В зависимости от использованных режимов адресации команда MOV может осуществлять пересылки следующих видов:
- из регистра общего назначения в регистр общего назначения;
- из ячейки памяти в регистр общео назначения;
- из регистра общего назначения в ячейку памяти;
- непосредственный операнд в регистр общего назначения;
- непосредственный операнд в ячейку памяти;
- из регистра общего назначения в сегментные регистры DS, ES и SS;
- из сегментного регистра в регистр общего назначения;
- из сегментного регистра в ячейку памяти.
Запрещены пересылки из ячейки памяти в ячейку памяти (для этого предусмотрена команда MOVS), а также загрузка сегментного регистра непосредственным значением, которое, таким образом, приходится загружать через регистр общего назначения:
mov AX, seg mem ;Сегментный адрес ячейки mem
mov DS, AX ;Загрузка его в регистр DS
Нельзя также непосредственно переслать содержимое одного сегментного регистра в другой. Такого рода операции удобно выполнять с использованием стека:
push DS ;
pop ES ;Содержимое DS копируется в ES
2). CMP (сравнение)
Команда CMP выполняет вычитание второго операнда из первого. В соответствии с результатом вычитания устанавливаются состояния флагов CF, PF, AF, ZF, SF и OF. Сами операнды не изменяются. Таким образом, если команду сравнения записать в общем виде:
cmp операнд_1, операнд_2
то ее действие можно условно изобразить следующим образом:
операнд_1 - операнд_2 -> флаги_процессора
В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака.
Обычно вслед за командой CMP стоит одна из команд условных переходов, анализирующих состояние флагов процессора.
3). Команды условных переходов Jcc
Команды, обозначаемые (в книгах, не в программах!) Jcc,осуществляют переход по указанному адресу при выполнении условия, заданного мнемоникой команды. Если заданное условие не выполняется, переход не осуществляется, а выполняется команда, следующая за командой Jcc.
Переход может осуществляться как вперед, так и назад в диапазоне +127...-128 байтов.
В составе команд процессора предусмотрены следующие команды условных переходов:
--------–-------------------------------------------
Команда | Перейти, если | Условие перехода
--------–-------------------------------------------
ja |выше |CF=0 и ZF=0
jae |выше или равно |CF=0
jb |ниже |CF=1
jbe |ниже или равно |CF=1 и ZF=1
jc |перенос |CF=1
jcxz |CX=0 |CX=0
je |равно |ZF=1
jg |больше |ZF=0 или SF=OF
jge |больше или равно |SF=OF
jl |меньше |SF не равно OF
jle |меньше или равно |ZF=1 или SF не равно OF
jna |не выше |CF=1 или ZF=1
jnae |не выше и не равно |CF=1
jnb |не ниже |CF=0
jnbe |не ниже и не равно |CF=0 и ZF=0
jnc |нет переноса |CF=0
jne |не равно |ZF=0
jng |не больше |ZF=1 или SF не равно OF
jnge |не больше и не равно |SF не равно OF
jnl |не меньше |SF=OF
jnle |не меньше и не равно |ZF=0 и SF=OF
jn |нет переполнения |OF=0
jnp |нет четности |PF=0
jns |знаковый бит равен 0 |SF=0
jnz |не нуль |ZF=0
jo |переполнение |OF=1
jp |есть четность |PF=1
jpe |сумма битов четная |PF=1
jpo |сумма битов нечетная |PF=0
js |знаковй бит равен 1 |SF=1
jz |нуль |ZF=1
--------–-----------------------–-------------------