Программирование в Debug

При написании работы использовались электронные справочники из старых запасов ))):
Help по MS Dos
и Основные команды assembler'a

Контрольная работа №1

 

Архитектура ЭВМ

 

            Целью данной лабораторной работы является знакомство с устройством вычислительной машины и взаимодействие программиста с аппаратной частью ЭВМ посредством программного обеспечения.

            Работа состоит из двух частей. В первой части необходимо описать одно из устройств компьютера, указанное преподавателем. Во второй части нужно написать программу на языке Ассемблер используя программу Debug , которая должна выполнять задачу, указанную преподавателем. Программа должна быть распечатана, иметь комментарии в каждой строке. Кроме того, нужно кратко описать устройства, которые используются в программе. Написанная программа должна быть сохранена на дискете и при защите работы должна быть загружена и запущена студентом на выполнение.

Для выполнения данной работы необходимо:

1.      Запустить Debug  через окно «Выполнить»

2.      Войти в режим ассемблирования, набрав а после приглашения

3.      Запустить программу на выполнение G=100

4.      Сохранить программу, используя команды N, R,W

5.      Уметь загрузить программу с дискеты командами N, L

 

Описание команд Debug дано в файле PAGE10. Debug (отладчик) входит в большинство операционных систем  DOS иWindows. Для изучения команд процессора, прерываний DOS и BIOS портов ввода\вывода смотри HELP1.

 

Варианты №4

 

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

выход:   AL = код символа, полученный из стандартного ввода.

 

Данная функция считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо).

 

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 просматриваем дамп памяти для определения адреса ввода последующей строки.

 

 

 

Прямоугольная выноска: адрес для ввода следующей строки 257Прямоугольная выноска: адрес для ввода следующей строки 26A

Прямоугольная выноска: адрес последнего байта в нашем блоке данных 296

 

 

 

 

 

Листинг программы

 

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 (AL = код введённого числа X) в

                        ` регистре CX  для последующего использования (сравнения)

mov ax, 900    `опять готовим функцию вывода на экран, AH = 09h

mov dx, 257    `адрес строки "Введите число Y ="

int 21               `вызываем прерывание DOS для выполнения функции вывода строки на экран

mov ax, 100    `готовим функцию ввода символа, AH = 01h

int 21               `выполняем эту функцию: программа ожидает ввода символа с клавиатуры

mov bx, ax      `копируем значение регистра ax (AL = код числа Y) в регистр bx

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

--------–-----------------------–-------------------

 

Hosted by uCoz