
Ассемблер
Структура и образ памяти программы типа .EXE
-
ES DS PSP 256 байт
СS Сегмент IP команд
Сегмент данных
SS Сегмент SP
стека
PSP – префикс программного сегмента
title from lightbulb
text segment ‘code’
assume CS: text, DS:data
myproc proc
mov AX, data
mov DS, AX
-----------------
myproc endp
text ends
----------------
data segment
----------------
data ends
----------------
stack segment stack ‘stack’
dw 128 dup (0)
stack ends
end myproc
2. Идентификатор программного сегмента: слово в апострофах указывает класс «программный». Класс анализируется компоновщиком для компоновки загрузочного модуля, при этом сегменты, принадлежащие одному классу, загружаются в память друг за другом
3. Сопоставляет сегментные регистры и адресуемые ими сегменты
4. Имя процедуры
5. Инициализирует сегмент данных (настраиваем регистр данных на начало сегмента данных)
а) пересылает адрес в аккумулятор
б) из аккумулятора в сегмент данных
8. Конец процедуры
9. Конец сегмента
15. Описываем сегмент стека
Структура и образ памяти программы типа .COM
|
CS DS ES SS PSP 256 байт |
IP = 100h Сегмент команд и данных |
SP = FFFEh |
title from lightbulb
text segment ‘code’
assume CS:text, DS:text
org 100h ; резервирует 256 байт PSP
myproc proc
------------------------
myproc endp
--------определения данных----------------------
text ends
end myproc
Пример
TITLE COM-PROG
CODESG SEGMENT PARA ‘CODE’
ASSUME CS:CODESG, DS:CODESG, SS:CODESG, ES:CODESG
ORG 100h
BEGIN: JMP MAIN
;---------
FLDA DW 250
FLDB DW 125
FLDC DW ?
;---------
MAIN PROC NEAR
MOV AX, FLDA ;переслать 0250 в AX
ADD AX, FLDB ; прибавить 0125 в AX
MOV FLDC, AX ; записать сумму в FLDC
RET ; вернуться в DOS
MAIN ENDP
CODESG ENDS
END BEGIN
Устройство Управления декодирует байты программы и управляет работой операционного устройства и шинного интерфейса.
Связь с внешними устройствами осуществляется через специальные тристабильные схемы, называемые буферами.
Регистр флагов
По результатам операций АЛУ аппаратно устанавливает либо сбрасывает отдельные биты в регистре флагов. Слово состояния процессора (PSW) приведено на рисунке
15 0
|
OF |
DF |
IF |
TF |
SF |
ZF |
x |
AF |
x |
PF |
x |
CF |
x означает, что содержимое бита не имеет значения
CF – флаг переноса (carry) устанавливается, если в результате выполнения операции из старшего бита переносится или занимается единица при сложении или вычитании, иначе CF = 0. На CF влияют также команды сдвига и умножения
PF – флаг четности (parity) равен 1, если результат операции содержит четное число двоичных единиц
AF – флаг дополнительного переноса (auxiliary) устанавливается, если есть перенос из старшего бита младшей тетрады (бит D3) в младший бит старшей тетрады (бит D4). Используется в операциях над упакованными BCD
ZF – флаг\признак нулевого результата, устанавливается в единицу, если получен нулевой результат, иначе ZF = 0
SF – флаг знака результата (sign) равен единице, если результат отрицательный, т.е. он дублирует старший знаковый бит результата
TF – флаг трассировки (отладки). Если этот флаг установлен в единичное состояние , то процессор переходит в режим пошагового выполнения команд, т.е. после выполнения каждой команды генерируется внутреннее прерывание (тип 1) через вектор, расположенный по адресу 04
IF – флаг разрешения прерывания – если флаг установили в единицу, то прерывания микропроцессора от внешних устройств разрешены (микропроцессор распознает маскируемые прерывания)
DF – флаг направления
OF – флаг переполнения установки
CF, DF, IF можно изменять программно
команды STC, STD, STI устанавливают соответствующие флаги в 1
команды CLC, CLD, CLI устанавливают соответствующие флаги в 0
Пример: сложение однобайтовых чисел
125+4=129 – выходит за пределы чисел со знаком (-128 - +127), но для беззнаковых чисел результат корректный
Перенос в бит D7 равен 1. Флаги: OF = 1, CF = 0, ZF = 0, SF = 1, AF = 1
Резервирование памяти.
count dw 1000 // помещает значение 1000 по адресу count
coef dw 5, 10, 68 //указанными числами заполняются слова
mask db 0FFh // в байт с именем mask записывается FF
mes db ‘-смещение’
// байтовая строка с текстом «смещение» начиная с адреса mes
adr dw mes
// в слове adr смещение строки первого байта строки mes
addr dd myproc
//в двойном слове помещается двухместный адрес процедуры
В первом слове – относительный адрес
Во втором -сегментный
area dw 128 dup (?) // резервируем 128 слотов память
text db 100 dup (‘#’)
//100 байт массива заполняется кодом решетки
array dw 1024 dup (256)
//массив из 1024 слов, в каждом слове 256
константы
kilo equ 1024
//kilo – константа, которой присваивается значение 1024 навсегда
offs = 80-2*12+40*2
//начальное значение offs = ... Но в тексте программы можно менять
leng = FFFh
//leng – название числа FFFF
mes db ‘ждите’
meslen = $ - mes
Использование байта в словных операциях (оператор PTR)
Bits dw F4E9h
mov ax, bits //помещает в аккумулятор F5E9
mov bh, byte ptr bits
//пересылает в старший байт регистра младший байт (E9) переменной
mov clm byte ptr bits + 1
//пересылка старшего байта (F5) в cl
addr dd myproc
// в двойное слово помещается двухсловный адрес процедуры
mov bx, word ptr addr //относительный адрес myproc
move es, word ptr addr + 2 //сегментный адрес
Все переменные адресуются младшим байтам
Система команд
Семь групп режимов адресации:
Регистровая адресация
Непосредственная адресация
Прямая адресация
Косвенная регистровая адресация
Адресация по базе
Прямая адресация с индексированием
Адресация по базе с индексированием
Самые быстрые – регистровая и непосредственная, т.к. в этом случае операционный блок МП извлекает их либо из регистров, либо из конвейера команд
В других случаях адресация выполняется дольше, потому что интерфейс шины вначале должен вычислить адрес ячейки памяти, извлечь операнд и только потом передать его операционному блоку.
Регистровая адресация
Операнд извлекается из регистра
MOV AX, CX
INC CX
XCHG BX, BP
Непосредственная адресация
Константа является операндом-источником и содержится в команде
MOV CX, 500
MOV CL, -30
K EQU 1024
MOV CX, K
Прямая адресация
Исполнительный адрес является составной частью команды
MOV AX, TABLE
mem dw 0
……………….
inc mem
строгая запись
inc ds:mem
По умолчанию все смещения вычисляются относительно ds, поэтому его можно не указывать.
Обязательно указывать регистр
- для сегментных регистров ES, CS, SS
inc es:mem
- при обращении к памяти по известному АБСОЛЮТНОМУ адресу
mov al, ds:17h
mov bx, es:2ch
Косвенная регистровая адресация
Исполнительный адрес операнда содержится в базовом регистре BX, регистре указателя базы BP или в индексном регистре (SI или DI)
Операнды заключаются в квадратные скобки
При использовании BX, SI или DI подразумевается регистр DS
При использовании BP подразумевается регистр SS
MOV BX, OFFSET TABLE
MOV AX, [BX]
эти две команды выполняют те же действия, что и команда
MOV AX, TABLE
Адресация по базе
Исполнительный адрес вычисляется с помощью сложения значения сдвига с содержимым регистров BX или BP
MOV AX, [BX]+4 // если начальный адрес записи в BX, то в AX загрузится 5 и 6 байты от начала записи.
эта команда эквивалентна
MOV AX, 4[BX]
MOV AX, [BX+4]
Прямая адресация с индексированием
Исполнительный адрес вычисляется как сумма значений сдвига и индексного регистра (DI или SI). Тип адресации удобен при работе с таблицами, когда сдвиг указывает на начало таблицы, а индексный регистр – на её элемент
Например если TABLE – таблица байт, то последовательность команд
MOV DI, 2
MOV AL, TABLE [DI]
загрузит третий элемент таблицы TABLE в регистр AL
Адресация по базе с индексированием
Исполнительный адрес вычисляется как сумма значений базового регистра, индексного регистра и возможно сдвига. Удобен при адресации двумерных массивов
MOV AX, TABLE [BX][DX]
возможна также следующая запись
MOV AX, TABLE[BX+2][DX]
MOV AX, TABLE [BX][DX+2]
Пример 1:
MOV CX, L ;инициализация счетчика
MOV SI, -1 ; инициализация индекса
MOV AL, 20h ; код пробела
NEX: INC SI ; увеличение индекса
CMP AL, STR [SI] ; сравнение с пробелом
LOOPNE NEX ; цикл пока CX не 0 и не пробел
JNZ ST ; если CX = 0, но не пробел
Пример 2:
array db 0, 10, 20, 30, 40, 50, 60, 70, 80, 90
mov bx, 5
mov al, array[bx]
или
mov bx, offset array
mov al, 5[bx]
Пример 3:
syms db ‘ЙЦУКЕНГШЩЗХЪ’
‘QWERTYUIOP[]’
…………………………
mov bx, 12
mov si, 6
mov dl, syms[bx][si]
Циклы
Команда LOOP служит для выполнения конечного числа циклов, использует начальное значение в регистре CX. В каждом цикле команда LOOP автоматически уменьшает содержимое СХ на 1. Пока значение СХ не будет равно 0, управление передается по адресу, указанному в операнде; если в СХ будет 0, управление переходит на следующую после LOOP команду
Разновидности:
1. LOOPE (LOOPZ) – передает управление, если СХ имеет ненулевое значение и флаг нуля установлен
2. LOOPNE (LOOPZE) – передает управление, если СХ имеет ненулевое значение и флаг нуля сброшен
Пример 1:
array dw 1024 dup (?)
mov cx, 1024
lea bx, array
mov si, 0
адрес массива помещен в ВХ
null: mov [bx][si], 0 //очищаем содержимое
inc si
inc si
loop null
loop уменьшает значение СХ на 1, если в СХ не 0, то переходит на метку
Пример 2: //фрагмент программы задержки выполнения
mov cx, 10
outer: push cx // сохраняем СХ в стеке
mov cx, 0 // пересылаем в СХ 0
tun: loop tun //цикл, вычитает 1, если не 0, то на метку
pop cx //восстанавливает значение из стека СХ
loop outer