
- •Программирование эвм
- •Int 21h ;кодом возврата 0 прерывания 21h
- •Работа с битами
- •Порядок выполнения работы
- •Устройства ввода-вывода
- •Ввод исходных данных с клавиатуры и вывод результатов на дисплей
- •Inc di ;смещение в видеопамяти на следующий символ
- •Порядок выполнения работы
- •Контрольные задания
- •Система команд процессора
- •Способы адресации
- •Влияние команд на регистр флагов
- •Расширенные регистры и типы данных процессоров x86
- •Система команд процессоров ia-32 и Intel 64
- •Int 21h ;системного прерывания 21h
- •Использование дальней подпрограммы
- •X dw 0aabBh, 0abbAh, 0baaBh, 0bbaAh ;исходные данные
- •Использование подпрограмм для ввода-вывода
- •Порядок выполнения работы
- •Контрольные задания
- •Дескрипторы
- •Порядок работы процессора в защищенном режиме
- •Использование дальней подпрограммы в защищенном режиме
- •Использование idt. Ввод данных с клавиатуры в защищенном режиме
- •Порядок выполнения работы
Int 21h ;кодом возврата 0 прерывания 21h
code ends ;объявление конца сегмента кода
end begin ;конец программы
Программа включает два сегмента: сегмент данных с именем data и сегмент кода с именем code. Сегмент — это область памяти, адрес начала которой определяет специальный регистр — сегментный регистр. Имена и количество сегментов могут быть любыми с определенными ограничениями. Сегментных регистров бывает несколько, каждый из них указывает на свой сегмент. Адрес информационной единицы, переменной или команды, внутри сегмента отсчитывается от его начала и называется смещением. Таким образом, полный адрес представляет собой пару "сегмент:смещение", которая называется логическим адресом.
Для компиляция программы можно использовать любой ассемблер, например, TASM (Turbo Assembler) компании Borland. Имя файла ассемблера — tasm.exe.
Командная строка для компиляции (табл.5):
tasm sum
В результате будет создан файл с объектным кодом sum.obj.
Для компоновки можно использовать программу tlink.exe из того же пакета:
tlink sum
В результате будет создан исполняемый файл с объектным кодом sum.exe. Если его запустить, то никакого видимого эффекта не будет. Программа никак не взаимодействует с внешними устройствами, ничего не вводит и ничего не выводит. Исходные данные читаются процессором из памяти, результат также помещается в память. Исследовать работу программы можно с помощью отладчика td.exe:
td sum
Таблица 5.
Компиляция и компоновка программы
№ |
Командная строка |
Преобразование |
1 |
tasm filename |
filename.asm -> filename.obj |
2 |
tlink filename |
filename.obj -> filename.exe |
Расширения имен файлов писать не обязательно, если они стандартные. В этом случае компилятор и компоновщик правильно найдут нужные им файлы. Иногда компилятору и компоновщику требуется задавать дополнительные параметры. Если компилятору необходимо сделать несколько проходов, то задается параметр "m":
tasm /m filename
Если в программе используются 32-разрядные операнды и адреса, то компоновщику надо задать параметр "3":
tlink /3 filename
Листинг программы
При компиляции программы можно задать параметр "l" (listing):
tasm /l sum
Тогда кроме файла с объектным кодом sum.obj будет создан файл с листингом sum.lst:
1 ;sum.asm – программа, вычисляющая S=A+B
2 0000 data segment
3 0000 0001 a dw 01h
4 0002 0002 b dw 02h
5 0004 ???? s dw ?
6 0006 data ends
7 0000 code segment
8 assume ds:data
9 0000 BA 0000s begin: mov dx, data
10 0003 8E DA mov ds, dx
11 0005 A1 0000r mov ax, a
12 0008 03 06 0002r add ax, b
13 000C A3 0004r mov s, ax
14 000F B8 4C00 mov ax, 4C00h
15 0012 CD 21 int 21h
16 0014 code ends
17 end begin
Листинг — это таблица, содержащая четыре столбца:
-
Номер строки.
-
Адрес внутри сегмента, т. е. от его начала (смещение).
-
Содержимое памяти по данным адресам. В сегменте данных — это значения переменных, в сегменте кода — это машинные коды команд.
-
Ассемблерный код.
Комментарии в листинге также сохраняются, просто здесь они для экономии места опущены.
Из листинга видно, что командам процессора соответствуют только строки 9-15. Остальные строки соответствуют т. н. директивам ассемблера.
В любом деле фигурирует информация различных уровней. Есть информация непосредственно о задаче, а есть информация об информации — метаинформация. Это, например, различные пояснения, указания и т. п. В исходном коде на языке ассемблера присутствует информация двух типов:
-
команды — информация для процессора;
-
директивы — информация для самого ассемблера, как скомпилировать программу: как перевести команды на машинный язык и как разместить данные.
Здесь есть аналогия с выделением типов команд. Команды передачи данных, передачи управления и арифметическо-логические команды несут информацию о задаче, а команды машинного управления — об условиях ее выполнения, т.е. тоже представляют собой метаинформацию.
В рассматриваемой программе имеются следующие директивы:
-
segment — директива объявления начала сегмента;
-
dw (define word) — директива определения данных (выделения и инициализации области памяти) размером 16 бит;
-
ends (end segment) — директива объявления конца сегмента;
-
assume — директива назначения сегменту сегментного регистра;
-
end — директива указания конца программы, ее аргументом должна быть метка первой команды программы — точки входа в программу.
Есть также следующие директивы определения данных:
-
db (define byte) — директива определения области памяти в 8 бит;
-
dd (define double word) — директива определения области памяти в 32 бита.
Существуют директивы, перед названием которых ставится точка. Из такого рода директив нам потребуются только директивы указания используемого набора команд той или иной модели процессора, например:
-
.386 — используются несистемные команды процессора i80386;
-
.386p — используются все команды процессора i80386, в том числе системные.
Строки 3-5 содержат директивы определения переменных A, B и S. В совокупности строки 3-5 и 9-15 содержат информацию для процессора — программу, включающую команды и данные. Они непосредственно отображаются на память компьютера.
Примеры программ
Работа с массивами
Для поддержи операций с массивами процессоры x86 имеют аппаратные и программные средства. К аппаратным средствам относятся базовые и индексные регистры:
-
BX, EBX, RBX — base (база) 16-, 32-, 64-бит соответственно;
-
SI, ESI, RSI — source index, индекс источника;
-
DI, EDI, RDI — destination index, индекс приемника.
Базовые регистры предназначены для хранения начального адреса массива, индексные — для хранения адреса текущего элемента массива. Программные средства работы с массивами включают специализированные команды, которые автоматически изменяют индексный регистр на величину элемента массива, настраивая его на следующий элемент, с большим или меньшим индексом, в зависимости от выбранного направления работы с массивом, которое определяет значение флага направления, содержащегося в регистре флагов.
Следующая программа осуществляет сравнение двух массивов до первого совпадения и определяет индекс первых совпавших элементов. На элементы первого массива arr1 указывает регистр ESI, второго — EDI. Базовые регистры в этой программе не используются.
;arrd.asm
;сравнение двух массивов 32-битных чисел до первого совпадения
;с определением индекса равных элементов
;compile:
;tasm
;tlink /3
.386
data segment
arr1 dd 1, 5, 7, 2
arr2 dd 2, 4, 7, 1
i dd ? ;переменная — индекс равных элементов
data ends
code segment use16
assume cs:code, ds:data, es:data
begin: mov dx, data
mov ds, dx
mov es, dx
mov esi, offset arr1 ;запись в ESI адреса начала массива arr1
mov edi, offset arr2 ;запись в EDI адреса начала массива arr2
mov ecx, 4 ;ECX — счетчик элементов массива
mov edx, ecx ;в EDX будет индекс равных элементов
repne cmpsd ;цикл чтения и сравнения до совпадения
sub edx,ecx ;в EDX индекс равных элементов
mov i, edx
mov ax, 4C00h
int 21h
code ends
end begin