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

Met_Lab2_121113

.pdf
Скачиваний:
16
Добавлен:
11.05.2015
Размер:
1.72 Mб
Скачать

EKDM

Пример макроопределения: OUTSTR MACRO Str PUSH АХ

PUSH DX MOV АН, 09h

MOV DX, OFFSET Str INT 21h

POP DX

POP AX ENDM

При выполнении макрорасширения для OUT_STR транслятор заменит этот макрооператор на тело макроопределения, причем он заменит формальный параметр Str в теле макроопределения на фактический параметр Buff. (В примере такая замена выполняется в единственном операторе MOV.)

Где расположить макроопределение? Здесь можно использовать два варианта. В первом из них макроопределение располагается в начале того же файла, где оно будет использоваться. Недостаток: в каждом файле, где предполагается использовать аналогичный макрооператор, его придется описывать заново. Во втором варианте макроопределение выносится в отдельный файл (текстовый ASCII-файл, полученный с помощью любого текстового редактора). А в начале каждого ассемблерного файла, где предполагается использовать макроопределение, записывается псевдооператор INCLUDE с указанием имени включаемого файла.

Например: INCLUDE Outstr.inc

Обычно в один включаемый файл помещают несколько макроопределений и, возможно, описания структур (которые фактически являются разновидностью макроопределений). При выполнении транслятором псевдооператора INCLUDE весь включаемый файл подсоединяется к тексту программы, содержащей INCLUDE, но на текст машинной программы наличие этого файла не влияет.

Полезно выполнить сравнение макроопределений с подпрограммами. Оба эти типа модулей позволяют программисту инициировать выполнение многих операторов с помощью единственного оператора (CALL или ВДТ для подпрограммы и макрооператор для макроопределения). Но механизм их реализации совершенно различен. В то время, как тело макроопределения будет записано транслятором всюду, где он встретит соответствующий макрооператор, тело подпрограммы находится в памяти в единственном экземпляре, а операторы CALL (или INT) выполняют передачу управления этому экземпляру. Отсюда можно сделать более обоснованным выбор между этими типами модулей.

Так как каждое выполнение подпрограммы связано с "накладными расходами" в виде двух инструкций (CALL и RET, или INT и DIET), то вклад этих инструкций в продолжительность выполнения тем больше, чем меньше подпрограмма. С другой стороны, чем длиннее тело макроопределения, тем больше затраты памяти на его "тиражирование". Следовательно, короткие повторяющиеся последовательности операторов лучше оформлять в виде макроопределений, а длинные - в виде подпрограмм.

71

Лабораторная работа № 2

Тема работы. Базовые операции вычисления.

Цель работы. Знакомство с арифметическими операторами языка Assembler. Содержание работы. В работе рассматривается программа, использующая

арифметические операторы - сложение, вычитание, умножение и деление. П р о г р а м м а 1

1IDEAL

2MODEL small

3STACK 256

4DATASEG

5

op_1

DD

11112222h

6

op_2

DD

3333DDDEh

7b_dst DB 32

8b_src DB 64

9w_src DW 512

10CODESEG

11Start: mov ax,@data

12mov ds,ax

13;Сложение операндов

14mov di,offset op_1

15mov si,offset op_2

16mov ax,[di]

17add ax,[si]

18mov [di],ax

19mov ax,[di+2]

20adc ax,[si+2]

21mov [di+2],ax

22;Умножение и деление

23mov al,[b_dst]

24Push al

25mul [b_src]

26neg [b_src]

27pop al

28imul [b_src]

29idiv [b_src]

30cbw

31mul [w_src]

32idiv [w_src]

33Exit: mov ax,4C00h

34int 21h

35END Start

Данная программа является автономной, она не получает никаких данных и не выводит никаких результатов, она предназначена для ознакомления с работой арифметических операторов.

Для того, что бы можно было наблюдать за работой программы, нужно запустить ее отладчике TurboDebugger (Td.EXE). Отладчик поможет проследить состояние регистров процессора на каждом шаге.

Задания к работе.

1.Добавьте в программу вычисление выражения 4+(12-35)/5 используя только регистры общего назначения AX,BX,CX и DX.

2.Добавьте в программу две числовые переменных с именами war1 и war2 размером в одно слово с любым на выбор начальным значением и рассчитайте значение выражения (war1*war2)/(war1+war2).

3.Добавьте в программу две любые числовые переменные и вычислите разность их квадратов.

72

3.6. Приложение к лабораторной работе № 2. Адресация

3.6.1. Форматы машинных команд и их кодирование

Общий формат команд процессора (начиная с модели i80386) приведён на рис 11.1. Команды состоят из необязательных префиксов, одного или двух байт кода операции, спецификаторов адреса (постбайт и байт sib), внутрикомандного смещения (Displacement) и непосредственных данных. Английские аббревиатуры означают следующее: Base – база, MoDe – режим, Register/Memory – регистр/память, Scale – масштаб, Index – индекс. Из всех полей команды обязательным является только один или два байта кода операции.

Префикс – это байт, который модифицирует операцию следующей за ним команды. Два префикса замены операнда и размера адреса (коды 66h и 67h соответственно) позволяют в реальном режиме изменить принимаемые по умолчанию 16-битные размеры операнда и эффективного адреса ЕА (Effective address) на 32-битные. Здесь необходимо заметить, что при ассемблировании машинной команды Tasm самостоятельно вставляет соответствующий префикс, если обнаруживает в мнемокоде команды 32-битный операнд или 32-битную ссылку на память.

Рис. 2.12. Общий формат команд

В реальном режиме может быть использован как 16-битный режим адресации памяти (единственно возможный в базовом процессоре i8086), так и 32-битный. Однако, учитывая, что в реальном режиме размер любого сегмента ограничен величиной 216 = 64 Кбайта, значение адреса в 32-битном слове не должно превышать величины FFFFh.

3.6.2. 16-битный режим адресации операндов в памяти

По функциональному признаку система команд разбивается на 6 групп: пересылка данных, арифметические операции, логические операции и сдвиги, передача управления, обработка цепочек и управления микропроцессором. В этом разделе будет рассмотрено формирование машинных кодов команд процессора, которые могут адресовать один или два операнда и структурно принадлежат к одному из трёх типовых форматов, приведённых на рис.11.2.

Машинные форматы команд в зависимости от типа команды и способа адресации содержат от 1 до 6 байтов, из которых ключевыми являются первый (код операции) и второй (способ адресации). Штриховыми линиями на рис. 1.6 показаны необязательные байты

73

команд. Принципы кодирования полей отдельных байтов команд рассмотрим на примере наиболее общей формы двухоперандной команды.

Рис. 2.13. Типичные форматы команд: двухоперандные команды (а) и (б) и однооперандная (в)

w (Word) – однобитовое поле, идентифицирующее тип операнда: при w=1 команда оперирует словами, а при w = 0 – байтом;

d (Direction) – однобитовое поле, определяющее направление передачи операнда или результата. При d = 1 осуществляется передача операнда в регистр, определённый полем reg во втором байте, при d = 0 – передача из указанного регистра;

reg (Register) 3-битовое поле регистра, условно определяющее назначение второго операнда;

r/m (Register/Memory) – 3-битовое поле операнда, который может находиться в памяти или в регистре и условно считается первым;

md (Mode) – 2-битовое поле, показывающее (табл. 11.1.), как интерпретировать поле r/m при нахождении эффективного адреса EA первого операнда: если md = 11, то операнд содержится в регистре, в остальных случаях – в памяти.

Т а б л и ц а 2 . 1 .

Определение эффективного адреса

 

 

 

 

Поле md

 

 

 

 

 

 

 

 

 

Поле r/m

1 1

 

0 0

0 1

1 0

 

 

 

 

 

 

 

 

W=0

 

W=1

 

 

 

 

 

 

 

 

 

 

0 0 0

AL

 

AX

BX+SI

BX+SI+D8

BX+SI+D16

 

 

 

 

 

 

 

0 0 1

CL

 

CX

BX+DI

BX+DI+D8

BX+DI+D16

 

 

 

 

 

 

 

0 1 0

DL

 

DX

BP+SI

BP+SI+D8

BP+SI+D16

 

 

 

 

 

 

 

0 1 1

BL

 

BX

BP+DI

BP+DI+D8

BP+DI+D16

 

 

 

 

 

 

 

1 0 0

AH

 

SP

SI

SI+D8

SI+D16

 

 

 

 

 

 

 

1 0 1

CH

 

BP

DI

DI+D8

DI+D16

 

 

 

 

 

 

 

1 1 0

DH

 

SI

BP

BP+D8

BP+D16

 

 

 

 

 

 

 

1 1 1

BH

 

DI

BX

BX+D8

BX+D16

 

 

 

 

 

 

 

Когда операнд находится в памяти, то поле md определяет вариант использования внутрикомандного смещения disp (Displacement), находящегося в 3-м и в 4-м байтах:

md=00, disp=0;

md=01, disp =disp 1-знаковое 8-битовое смещение (D8), расширяющееся со знаком до 16 бит при вычислении эффективного адреса ЕА;

md=10, disp =disp 11, disp 2-знаковое 16-битовое смещение (D16).

При этом кодировка поля reg второго операнда или поля r/m первого операнда при md = 11 определяет тип регистра в зависимости от значения параметра w. При md=11

74

реализуются косвенные виды адресации памяти, что и отражено в табл. 11.2. (исключение составляет случай прямой адресации при r/m = 110 и md = 00). Таким образом, в процессоре i8086 реализовано 24 варианта (8*3) вычисления эффективного адреса ЕА.

 

 

Т а б л и ц а 2 . 2 .

Косвенные виды адресации

 

 

 

 

 

Тип адресации

Способ вычисления EA

Число тактов

 

 

 

Косвенная

[BX], [BP], [SI], [DI]

5

Базовая, или индексная

[BX+ , BP+ , SI+ , DI+disp]

6

Базовая индексная без смещения

[BP+DI], [BX+SI]

7

 

[BP+SI], [BX+DI]

8

 

[BP+DI+disp]

11

Базовая индексная со смещением

[BX+SI+disp]

11

 

[BP+SI+disp]

12

 

[BX+DI+disp]

13

 

 

 

Замечание. Подчеркнём смысловое различие двух случаев употребления термина смещение. Смещение disp, содержащееся в команде, интерпретируется как знаковое число, которое участвует в вычислении эффективного адреса EA. С другой стороны, из-за сегментной организации памяти эффективный адрес EA является смещением OFFSET относительно базового адреса сегмента и интерпретируется как беззнаковое число при вычислении физического адреса.

При вычислении физического адреса эффективный адрес (или смещение Offset) сегментируется регистром DS (сегмент данных) во всех случаях кроме тех, когда в формировании EA участвует сегментный регистр BP. Использование регистра BP в формировании EA предопределяет сегментирование адреса по регистру SS (сегмент стека). Чтобы изменить, указанное по умолчанию сегментирование адресов, предусмотрена специальная однобайтная команда-префикс замены сегмента:

001 Sreg 110 – формат команды префикса замены.

Если команде предшествует префикс замены, то при обращении к данным в процессе исполнения команды участвует сегментный регистр из префикса. Кодировка поля Sreg в префиксе: 00 – ES, 01 – CS, 00 – SS, 11 – DS.

На рис. 11.2 б представлен формат двухоперандной команды с непосредственным операндом. В этом формате отсутствует необходимость в адресации второго операнда и поле reg отдано для расширения поля COP. Отсутствует также бит направления d, т.к. результат операции размещается на месте первого операнда. Место бита d занял бит s, функции которого определяются следующим образом:

sw = X0, data = data L -один байт данных;

sw = 01, data = dataH,dataL – два байта данных;

sw = 11, data = dataL – один байт данных, который расширяется со знаком до двух

байт.

Постбайтовая адресация является универсальной адресацией и позволяет адресовать как общие регистры, так и ячейки памяти. Однако при адресации только регистров или аккумулятора Acc постбайт оказывается излишним, если поле reg разместить в первом байте

75

команды или использовать неявную адресацию. Эта возможность реализуется в специальных укороченных форматах, которые содержат минимальное число байтов и, выбираются Turbo Assembler в процессе ассемблирования.

Двоичное кодирование ассемблерных команд, рекомендуется выполнять в следующей последовательности:

находим обобщённое представление команды, соответствующее одной из альтернативных записей команды в справочном списке команд (Приложение П.1.1);

для выбранного обобщённого представления команды выписываем из таблицы её формат;

принимая во внимание формат данных, способ кодирования регистров и тип адресного выражения для операнда, находящегося в памяти (табл. 1.2) , определяем двоичный код для обозначенных в команде полей;

записываем структурированный по байтам машинный код команды с использованием 16-теричных символов. Полученный код должен совпадать с машинным кодом соответствующей команды из окна CPU Turbo Debugger для рассматриваемого файла.

76

4. Сервисные функции DOS

4.1.Сервисные функции DOS ввода-вывода информации. Обработка строковых переменных

Вызовы функций MS-DOS для ввода-вывода символьной информации

Для того чтобы написать простую, но законченную программу, необходимо знать три вещи – как вводить данные, как выводить результат и как остановить выполнение программы. В языках высокого уровня имеются специальные операторы ввода/вывода, которые позволяют в удобной форме реализовать эти функции. В системе команд процессора ix86 также имеются команды ввода/вывода, но они реализуют эти операции на самом низком, физическом уровне, т.е. обеспечивают обращение к портам ввода/вывода по конкретным адресам. Для обеспечения ввода/вывода информации на этом уровне программист должен знать номера портов каждого устройства, а также протоколы или алгоритмы обслуживания этих устройств. Операционная система MS DOS реализует ряд сервисных функций ввода/вывода на логическом уровне, которые выступают как пронумерованные функции прерывания 21h. При этом прикладная программа пользователя должна сообщить необходимые для данной функции параметры и передать управление DOS, которая и осуществит все необходимые операции по управлению устройством на физическом уровне (где-то, возможно, обратится за помощью к BIOS), а затем вернёт управление прикладной задаче, сообщив, успешно ли завершилась операция или же была допущена ошибка.

Прерывания, в основном, можно разделить на два основных типа: аппаратные (hardware) и программные (software interrupt). Аппаратные прерывания вызываются сигналами от периферийных устройств, требующими обслуживания процессором, а программные, через посредством команды INT, вызывающей какую-либо сервисую функцию (процедуру) DOS или BIOS.

Упрощенная схема обработки прерывания изображена на рис. 12.1. Процессор выполняет команду прерывания, используя таблицу векторов, где содержатся все адресные указатели обработчиков (аппаратных и программных) прерываний. Действия процессора при переходе на выполнение подпрограммы-обработчика (инициируемое командой I0T n) и последующем возврате обратно (при встрече команды IRET) в точку выхода из основной программы показаны на рис. 12.1. цифрами в кружках. Одно и то же прерывание может выполнять несколько различных функций, код которых помещается в регистр AH, а дополнительные параметры заносятся в другие регистры РОН (регистры общего назначения). Возвращаемая обработчиком информация содержится в регистре AL или AX, если флаг CF=0. Флаг CF устанавливается в 1, если произошла какая-либо ошибка, код которой заносится в регистр AX (так называемый код возврата ошибки). Возможные коды ошибок приводятся в руководствах по DOS.

77

Рис. 3.1. Упрощенная схема обработки программного прерывания INT n

Функции информационного обмена MS DOS в своём развитии изменялись от специализированных программ обмена для каждого типа устройства на основе блока управления файлами FCB (File Control Block) до унификации обмена на основе файловой системы через дескрипторы. Дескриптор или логический номер файла идентифицирует файл или устройство, с которым должна работать прикладная программа. Это упрощает программирование операций ввода/вывода, т.к. позволяет осуществлять обмен информации независимо от природы файла (устройства). Существует пять стандартных дескрипторов файлов, которые предоставляются прикладной программе:

0 – стандартный ввод с консоли (обычно клавиатура);

1 – стандартный вывод на консоль (обычно экран дисплея);

2 – устройство вывода ошибок (всегда дисплей);

3 – внешнее устройство обмена AUX (асинхронный адаптер COM1);

4 – стандартный принтер (первый параллельный порт LPT1).

Стандартный ввод (как и стандартный вывод) можно перенаправить средствами DOS

на любое устройство или в файл, а стандартная ошибка всегда связана с экраном (обычно дескриптор 2 используют для вывода диагностических сообщений). Перенаправление ввода или вывода программы осуществляет командный процессор Command.com. Если, допустим, в программе prog предусмотрен ввод данных через дескриптор стандартного ввода 0, а вывод данных через дескриптор вывода 1, то при обычном запуске программы командой prog.exe программа будет требовать входные данные с клавиатуры и выводить результаты своей работы на экран. Если, однако, при запуске программы использовать символ перенаправления

prog.exe > file.txt

то система сама создаст файл file.txt, и весь вывод программы будет записан в этот файл. Ввод по-прежнему будет осуществляться с клавиатуры. Запуск программы командой

prog.exe < file.dat

78

приведёт к тому, что программа всю требуемую ей информацию попытается ввести из файла file.dat. Поэтому этот файл должен быть подготовлен пользователем заранее. Вывод программы опять поступит на экран. Наконец, команда

prog.exe < file.dat > file.txt

заставит программу выполняться в режиме ввода информации из файла file.dat и

вывода в файл file.txt. Ни экран, ни клавиатура использоваться не будут. Сама программа ничего не знает об этих перенаправлениях – она во всех случаях обращается к стандартному устройству ввода данных и к стандартному устройству вывода данных. Просто DOS как бы подставляет ей на входе и выходе другие устройства.

4.1.1. Ввод с клавиатуры символьной информации

Буфер ввода данных с клавиатуры

Нажатие любой клавиши клавиатуры вызывает сигнал аппаратного прерывания (прерывания с типом 09h), заставляющий процессор прервать исполняемую программу и перейти на подпрограмму обработки прерывания от клавиатуры. Обработчик прерывания формирует двухбайтовый код с последующей засылкой его в кольцевой буфер ввода данных с клавиатуры, располагающийся по адресу 0040h:001Eh в системной области оперативной памяти. Для алфавитно-цифровых клавиш старший байт этого кода представляет scan-код клавиши (условный номер клавиши на клавиатуре), а младший – ASCII-код клавиши, т.е. 8- битовый код закреплённого за этой клавишей символа.

Заполнение буфера клавиатуры, рассчитанного на 15 слов или ударов по клавишам, происходит по мере нажатия клавиш и не связано с выполнением текущей программы. Если программе требуется ввести с клавиатуры определённый символ (или строку), она с помощью соответствующей системной функции DOS обращается к буферу ввода и, при наличии в нём данных, передаёт первый из поступивших в этот буфер символов в программу. Дело в том, что запись и считывание кодовых слов в буфер клавиатуры соответствует принципу FIFO (first in – first out, первым вошёл – первым вышел), поэтому считывание символа из буфера освобождает место для ввода последующих. Если к моменту вызова функции DOS буфер ввода оказывается пуст, DOS будет непрерывно опрашивать его состояние, ожидая появления в буфере очередного кода, а исполнение программы приостанавливается до нажатия клавиши.

4.1.2. Системные функции DOS ввода данных с клавиатуры

DOS предоставляет несколько способов ввода данных с клавиатуры:

использование группы функций Int 21h (01h, 06h, 07h, 08h, 0Ah, 0Ch), обеспечивающих посимвольный ввод с клавиатуры в разных режимах;

обращение к клавиатуре, как к файлу, с помощью функции 3Fh.

Функции DOS, осуществляющие ввод с клавиатуры, различаются друг от друга

некоторыми другими важными характеристиками, которые приведены в табл. 12.1.

Т а б л и ц а 3 . 1 .

Сравнительная характеристика функций DOS ввода с клавиатуры

Номер функции DOS

01h

06h

07h

08h

0Ah

0Bh

0Ch

 

 

 

 

 

 

 

 

Эхо-символы

+

-

-

-

+

 

+/-

 

 

 

 

 

 

 

 

79

Реакция на Ctrl+C

+

-

-

+

+

+

+/-

 

 

 

 

 

 

 

 

Перенапрвление

+

+

+

+

+

+

+

 

 

 

 

 

 

 

 

Ожидание нажатия клавиши

+

-

+

+

+

-

+

 

 

 

 

 

 

 

 

Ввод расширенных кодов ASCII

+

+

+

+

-

 

+

 

 

 

 

 

 

 

 

Очистка буфера

-

-

-

-

-

 

+

 

 

 

 

 

 

 

 

Ввод кодов с помощью Alt/цифра

-

+

+

+

-

 

+/-

 

 

 

 

 

 

 

 

Эхо-символы. Отображение вводимого символа на экране.

Реакция на Ctrl+C. Аварийное завершение программы (ASCII-код 03h). Вызывается обработчик прерывания Int 23h, завершающий текущую программу с выходом в DOS.

Ожидание нажатия клавиши. Функция, при отсутствии символа в кольцевом буфере ожидает его ввода. Функции, обладающие этим свойством, являются синхронными, иначе – асинхронными.

Ввод расширенных кодов ASCII. Все функции DOS, считывающие данные с клавиатуры, передают в программу только ASCII-код (младший байт кодового слова клавиши), оставляя scan-код (старший байт) без внимания. Правда, это относится только к алфавитно-цифровым клавишам, т. е. клавишам, за которыми закреплены отображаемые на экране символы (94 символа со значениями ASCII-кода от 32 до 126).

Очистка буфера. Процесс считывания кодов с буфера ввода может дать непредсказуемый эффект, если перед вызовом функции DOS этот буфер не был пуст. Программа, не желающая вводить набранные досрочно коды, должна очистить клавиатурный буфер с помощью специальной функции 0Ch прерывания 21h (при al = 0).

Ввод кодов с помощью комбинации Alt/цифра. Позволяет вводить в программу коды символов второй половины ASCII-таблицы, с использованием цифровой клавиатуры (правая часть консоли).

Функция 01h. Ввод одиночного символа с эхом.

Вводит символ из стандартного устройства ввода и отображает его на устройстве стандартного вывода. Ввод каждого символа сопровождается перемещением курсора вправо на следующую позицию. При отсутствии символа ждёт ввода. При наборе строки обрабатываются управляющие клавиши: BS (шаг назад без удаления символа, AL = 08h), TAB (табуляция, AL = 09h), E0TER (переход на начало текущей строки, AL = 13h). Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет обработку <Ctrl/C>. Для чтения расширенного кода ASCII требует повторного выполнения функции.

Вызов: AH = 01, Int 21h. Выход: AL = код символа.

Функция 06h. Ввод одиночных символов из стандартного устройства ввода и вывод одиночных символов на стандартное устройство вывода.

Режим работы определяется содержанием регистра DL в момент вызова функции: DL = FF – режим ввода, DL = {FFh – 00h } – режим вывода соответствующего этому коду символа. В режиме вывода коды ASCII: 07h – звонок, 0Dh – возврат каретки, 0Ah – перевод строки, рассматриваются как управляющие и выполняются соответствующие им действия.

Если вводимый символ в устройстве ввода присутствует, то он помещается в AL (без эха) с установкой флага ZF = 0, иначе ZF = 1. Отличительным качеством функции 06h

80

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]