1) Программа должна содержать только один сегмент – сегмент команд и размер программы не должен превышать 64 кБ.
2) Сегмент стека в программе не создается, т.к. он создается автоматически в области PSP при загрузке программы.
3) Сегмент данных в программе не создается. Исходные данные и константы, необходимые для работы программы, определяются в начальной части сегмента команд.
4) Директивой ASSUME все сегментные регистры связываются с сегментом команд. Начальный адрес сегмента команд смещается директивой ORG на величину 100H, т.к. в диапазоне ячеек 0-100H будет размещаться область PSP со стековой памятью.
Пример построения исходного модуля для COM-программы:
Директива ASSUME связывает регистры CS, DS и SS с одним сегментом – сегментом команд.
Программа BEGIN начинается командой безусловного перехода на процедуру MAIN – JMP MAIN.
Процедура MAIN имеет не тип FAR а тип NEAR, это означает, что процедура MAIN не является началом программы. Началом программы является команда JMP MAIN.
Директива ENDP закрывает процедуру MAIN.
Директива ENDS закрывает сегмент команд.
Директива END закрывает всю программу.
Тема 7. Определение данных в ассемблерной программе
Данные для ассемблерной программы определяются в сегменте данных для EXE-формата и в сегменте команд, после первой команды JMP для COM-формата.
Формат команды для определения данных имеет вид:
[Имя] Команда Операнд
FLD DB 25
В этом примере задается десятичная константа размерностью 1 Байт с именем FLD.
FCS DB 10H
В этом примере задается шестнадцатеричная константа размерностью 1 Байт с именем FCS.
DRT DB 01100001B
В этом примере задается двоичная константа размерностью 1 Байт с именем DRT.
TOL DB ?
В этом примере задается неопределенная константа размерностью 1 Байт с именем TOL.
SSC DB 11,12,13
В этом примере задается поле с именем SSC, содержащее 3 однобайтовые десятичные константы.
Для определения данных используются следующие команды Ассемблера:
1) DB – эта команда используется для задания констант размерностью 1 Байт.
2) DW – эта команда используется для задания констант размерностью 1 Слово (2 Байта).
3) DD – эта команда используется для задания констант размерностью Двойное слово (4 Байта).
4) DQ – эта команда используется для задания константы размерностью Два двойных слова (8 Байт).
Для повторного задания одной и той же константы используется оператор DUP.
DW 10 DUP(?)
Эта команда задает 10 неопределенных констант, размерностью 2 Байта каждая. Общий размер поля 20 Байт.
DB 5 DUP(14)
Эта команда задает 5 десятичных констант, имеющих значение 14 и размерностью 1 Байт каждая. Общий размер поля 5 Байт.
DB 3 DUP(4 DUP (8))
Эта команда задает 3 группы констант. В каждой группе по 4 десятичные константы со значением 8. Каждая константа имеет размерность 1 Байт. Общий размер поля 12 Байт.
FLK DB ‘NAME’
Эта команда задает символьную константу с именем FLK. Константа содержит 4 символа: N, A, M и E. Каждый символ кодируется 1 Байтом. Общий размер поля 4 Байта.
Команды DW, DD, DQ константы записываются в ячейки памяти побайтово в обратной последовательности.
Пример:
DW 3039H
В этом примере определяется двухбайтовая шестнадцатеричная константа, где 39Н – это младший байт константы, а 30Н – это старший байт константы.
Константа
Старший Байт
Младший Байт
№1
№0
Младший байт константы записывается в младшую нулевую ячейку, а старший байт константы записывается в старшую первую ячейку памяти.
Память
Младшая ячейка
Старшая ячейка
№0
№1
При просмотре дампа памяти на экране монитора константа будет выглядеть – 39 30.
Примеры использования регистров и данных в командах.
MOV AX,BX
Эта команда выполняет пересылку содержимого регистра BX в регистр AX.
MOV AX,WORDA
Эта команда выполняет пересылку содержимого поля с именем WORDA, определенном в сегменте данных, в регистр AX.
LEA AX,WORDA
Эта команда выполняет загрузку адреса поля с именем WORDA, определенном в сегменте данных, в регистр AX.
MOV AX,[BX]
Эта команда выполняет пересылку содержимого ячейки памяти, адрес которой указан в регистре BX, в регистр AX.
MOV AX,25
Эта команда записывает число 25 в регистр AX.
MOV AX,[25]
Эта команда выполняет пересылку содержимого 25й ячейки памяти в регистр AX, где 25 – это относительный адрес ячейки в сегменте данных.
Тема 8. Организация переходов в ассемблерной программе
При выполнении ассемблерной программы команды выполняются последовательно одна за другой в том порядке, как они записаны программистом.
Некоторые команды могут передавать управление, изменяя нормальную последовательность выполнения команд.
Существуют 4 способа передачи управления в программе с использованием следующих команд:
1) JMP – безусловный переход.
2) LOOP – цикл.
3) Jnnn – условный переход.
4) CALL – вызов процедуры.
JMP
Для команды JMP необходимо указать метку, по которой происходит переход:
JMP A20
В том месте, куда нужно перейти процессору, устанавливается эта метка с двоеточием – А20:
LOOP
Команда LOOP работает, так же как команда JMP, но совершает не один переход а несколько переходов. Количество переходов (так называемых циклов) указывается в регистре СХ. Установка регистра СХ должна быть выполнена перед меткой, по которой происходит переход.
С каждым новым переходом (циклом) число в регистре СХ уменьшается на 1. Когда число в регистре СХ уменьшится до 0 действие команды LOOP заканчивается и программа выходит из цикла.
Jnnn
Команд условного перехода имеется большое количество. Такие команды работают как и JMP, но обеспечивают переход только при выполнении конкретного условия. Условие проверяется по регистру флагов.
Если условие не выполняется, то команда условного перехода не работает, и выполнение программы идет в обычном порядке.
Пример:
JZ A20
По этой команде переход на метку А20 произойдет если во флаговом регистре будет установлен признак нуля Z. Установка признака нуля означает, что при выполнении предыдущей команды в АЛУ получен результат, равный 0.
CALL
Для команды CALL необходимо указать имя процедуры, на которую нужно сделать переход:
CALL MULS
По этой команде происходит переход на процедуру MULS. После выполнения всех команд процедуры MULS процессор возвращается в основную процедуру и будет выполнять команду, следующую после команды CALL.
Тема 9. Арифметичесике операции
Сложение чисел выполняется командой ADD:
ADD AX,BX
По этой команде к содержимому регистра АХ прибавляется содержимое регистра ВХ, результат сложения записывается в регистр АХ.
AX
10H
00010000B
BX
04H
00000100B
AX
14H
00010100B
Вычитание чисел выполняется командой SUB:
SUB AX,BX
По этой команде из содержимого регистра AX вычитается содержимое регистра BX, результат вычитания записывается в регистр AX.
00000100B
AX
10H
11111011B
00010000B
BX
04H
1B
11111100B
AX
0СH
11111100B
00001100B
Двоичные числа могут кодироваться в беззнаковом формате и в знаковом формате. В беззнаковом формате в прямом двоичном коде представляются положительные числа, отрицательные числа кодируются в дополнительном двоичном коде.
В знаковом формате старший седьмой бит в байте является не числовым, а знаковым. Если знаковый бит имеет значение 0, то число считается положительным. Если знаковый бит имеет значение 1, то число считается отрицательным. Остальные 7 младших бит в байте являются числовыми и представляют либо положительное число в прямом двоичном коде, либо отрицательное число в дополнительном двоичном коде.
Беззнаковый формат
Знаковый формат
Десятичное
Двоичное
Десятичное
Двоичное
+1
0000 0001
+1
0.000 0001
+2
0000 0010
+2
0.000 0010
+5
0000 0101
+5
0.000 0101
+11
0000 1011
+11
0.000 1011
+121
0111 1001
+121
0.111 1001
+127
0111 1111
+127
0.111 1111
+137
1000 1001
-119
1.000 1001
+246
1111 0110
-10
1.111 0110
+249
1111 1001
-7
1.111 1001
+252
1111 1100
-4
1.111 1100
Если при сложении знаковых чисел полученный результат выходит за пределы диапазона -128 --- +127, то возникает ошибка сложения.
Двоичное
Десятичное
+121
+11
-124
Ситуация, при которой в результате сложения двоичных чисел в полученной сумме появляется единица в старшем седьмом бите называется - переполнение. При возникновении переполнения результат сложения знаковых чисел будет неправильным.
Двоичное
Десятичное
-10
-119
+127
Ситуация, при которой в результате сложения двоичных чисел в полученной сумме единица вытесняется за пределы байта, т.е. образуется 9-битовое число, называется – перенос. При возникновении переноса результат сложения знаковых чисел будет неправильным.
Двоичное
Десятичное
-4
+5
+1
Если при сложении знаковых чисел происходит и переполнение и перенос, то результат сложения получается правильным.
Двоичное
Десятичное
+121
+11
+132
Если при сложении беззнаковых чисел происходит переполнение, то результат получается правильным.
Двоичное
Десятичное
+246
+137
+127
Если при сложении беззнаковых чисел, происходит перенос, то результат получается неправильным.
Двоичное
Десятичное
+252
+5
+1
Если при сложении беззнаковых чисел происходит и переполнение и перенос, то результат получается неправильным.
В тех примерах, где получается неправильный результат, необходимо исключить ситуацию переноса или переполнения. Для этого увеличивают разрядность двоичных чисел, делая числа двухбайтовыми.
Для умножения беззнаковых чисел используется команда MUL.
Для умножения знаковых чисел используется команда IMUL.
Для деления беззнаковых чисел используется команда DIV.
Для деления знаковых чисел используется команда IDIV.