-
Notifications
You must be signed in to change notification settings - Fork 2
Лекция 2
| Номер параграфа начала сегмента |
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
| Смещение |
[SEG]:[OFFSET]
=> физический адрес:
- SEG необходимо побитово сдвинуть на 4 разряда влево (или умножить на 16, что тождественно)
- К результату прибавить OFFSET
5678h:1234h =>
56780
+ 1234
= 579B4
Вычисление физического адреса выполняется процессором аппаратно, без участия программиста. Распространённые пары регистров: CS:IP, DS:BX, SS:SP.
- Сегмент кода (регистр CS)
- Сегменты данных (основной регистр - DS, для дополнительных сегментов - ES, FS, GS)
- Сегмент стека (регистр SS)
LOOP метка
Уменьшает регистр CX на 1 и выполняет переход на метку, если CX не равен нулю. Метка не может быть дальше -128..127 байт от команды.
- Модули (файлы исходного кода)
- Сегменты (описание блоков памяти)
- команды процессора;
- инструкции описания структур данных, выделения памяти для переменных и констант;
- макроопределения.
- Сегменты (описание блоков памяти)
метка команда/директива операнды ; комментарий
- В коде:
mov cx, 5
label1:
add ax, bx
loop label1
(5 раз прибавляем bx к ax)
Метки обычно используются в командах передачи управления.
- В данных:
-
label
метка label тип
- Возможные типы:
- BYTE (1 байт)
- WORD (2 байта)
- DWORD (4 байта)
- FWORD (6 байт)
- QWORD (8 байт)
- TBYTE (10 байт)
- NEAR - тип для хранения меток в коде или адресов команд для меток ближнего перехода
- FAR - тип для хранения меток в коде или адресов команд для меток дальнего перехода
-
EQU, =
-
label EQU выражение
(Пример выражения: 5 + 2, вычисляется на этапе компиляции) - Макрос
- Вычисляет выражение в правой части и приравнивает его метке
-
-
Директива - инструкция ассемблеру, влияющая на процесс компиляции и не являющаяся командой процессора. Обычно не оставляет следов в формируемом машинном коде. Псевдокоманда - директива ассемблера, которая приводит к включению данных или кода в программу, но не соответствующая никакой команде процессора. Псевдокоманды определения данных указывают, что в соответствующем месте располагается переменная, резервируют под неё место заданного типа, заполняют значением и ставят в соответствие метку. Виды: DB (1), DW (2), DD (4), DF (6), DQ (8), DT (10). Примеры:
- a DB 1
- float_number DD 3.5e7
- text_string DB ‘Hello, world!’
DUP - заполнение повторяющимися данными
? - неинициализированное значение
uninitialized DW 512 DUP(?)
Любая программа состоит из сегментов.
Виды сегментов:
- сегмент кода
- сегмент данных
- сегмент стека
Описание сегмента - директива SEGMENT:
имя SEGMENT [READONLY] [выравнивание] [тип] [разрядность] [‘класс’]
...
имя ENDS
- BYTE (сегмент может начинаться с произвольного адреса)
- WORD (Адрес начала сегмента кратен 2 байтам)
- DWORD (Адрес начала сегмента кратен 4 байтам)
- PARA (сегмент располагается в начале параграфа, т.е. адрес начала сегмента кратен 16 байтам) - по умолчанию
- PAGE (сегмент располагается в начале страницы, т.е. адрес начала сегмента кратен 256 байтам)
- PUBLIC (сегменты с одним именем будут располагаться в памяти друг за другом независимо от порядка объявления)
- STACK (сегмент будет использоваться под стек (сегмент стека), все такие сегменты будут объединяться в один, увеличивая общий стек)
- COMMON (сегменты будут накладываться, т.е. начинаться с одного и того же адреса; память выделится по размеру наибольшего из сегментов; метки, на которые ссылаются сегменты, будут указывать на одни и те же ячейки памяти)
- AT (нужен аргумент - номер параграфа начала сегмента; сегмент будет загружаться в память по некоторому фиксированному постоянному адресу, независимо от расположения остальных сегментов)
- PRIVATE (сегмент не объединяется с другими) - по умолчанию
Класс - любая метка, взятая в одинарные кавычки. Сегменты одного класса будут расположены в памяти друг за другом.
.model модель, язык, модификатор
Служит для определения модели памяти программы. Позволяет сократить запись программ определённых типов.
- TINY - один сегмент на всё (как в случае COM-программы)
- SMALL - код в одном сегменте, данные и стек - в другом
- COMPACT - допустимо несколько сегментов данных
- MEDIUM - код в нескольких сегментах, данные - в одном
- LARGE, HUGE - много сегментов кода и данных
- C
- PASCAL
- BASIC
- SYSCALL, STDCALL
NEARSTACK (по умолчанию) или FARSTACK (ближний или дальний).
END [точка_входа]
- Точка_входа - имя метки, объявленной в сегменте кода и указывающее на команду, с которой начнётся исполнение программы.
- Если в программе несколько модулей, только один может содержать точку входа.
Для обращения к переменной
процессору необходимо знать обе
составляющие адреса: и сегментную, и
смещение.
Пример полной записи - DS:Var1
Директива ASSUME регистр:имя сегмента
устанавливает значение сегментного регистра по умолчанию
Data1 SEGMENT WORD 'DATA'
Var1 DW 0
Data1 ENDS
Data2 SEGMENT WORD 'DATA'
Var2 DW 0
Data2 ENDS
Code SEGMENT WORD 'CODE'
ASSUME CS:Code
ProgramStart:
mov ax,Data1
mov ds,ax
ASSUME DS:Data1
mov ax,Data2
mov es,ax
ASSUME ES:Data2
mov ax,[Var2]
.
.
.
Code ENDS
END ProgramStart
- Задание набора допустимых команд: .8086, .186, .286, …, .586, .686, ...
- Управление программным счётчиком:
-
ORG значение
- начиная с этой директивы в сегменте отступ будет идти со значением параметра директивы (пример:ORG 100h
- пропускает первые 256 байт) -
EVEN
- автоматически выравнивает всё, что идёт после неё, по чётным адресам -
ALIGN значение
- явно задаёт кратность выравнивания (выравнивание будет кратно параметру директивы); нужен для ускорения работы программы (можно поставить выравнивание по размеру машинного слова)
-
- Глобальные объявления:
-
public
- позволяет объявить метку доступной из других программ comm
-
extrn
- подключает метку из другого файла и делает её видимой в текущем файле (используется в связке с public) global
-
- Условное ассемблирование:
IF выражение
...
ELSE
...
ENDIF
- short (короткий): -128 .. +127 байт (аналогично команде loop)
- near (ближний): в том же сегменте (без изменения регистра CS, меняется только IP)
- far (дальний): в другой сегмент (с изменением значения в регистре CS)
- Для короткого и ближнего переходов непосредственный операнд (константа в коде) прибавляется к IP, а не заменяет его
- Операнды - регистры и переменные заменяют старое значение в IP (CS:IP)
- Команды различаются по занимаемому объёму памяти (far самый накладный)
- Регистры общего назначения (РОН):
- AX (AH, AL)
- BX (BH, BL)
- CX (CH, CL)
- DX (DH, DL)
- Индексные регистры:
- SI
- DI
- Сегментные регистры:
- CS
- DS
- ES
- FS
- GS
- SS
- Указательные регистры:
- SP
- BP
- FLAGS
- IP
- Могут использоваться в большинстве команд, как регистры общего назначения.
- Применяются в специфических командах поточной обработки данных (должно быть в 3 лекции).
- Регистровая адресация (
mov ax, bx
) - самый простой способ - Непосредственная адресация (
mov ax, 2
) - Прямая адресация (
mov ax, ds:0032
) - Косвенная адресация (
mov ax, [bx]
- bx взят в [], чтобы взять из него смещение). В 8086 допустимы BX, BP, SI, DI. - Адресация по базе со сдвигом (
mov ax, [bx]+2; <==> mov ax, 2[bx]
). Удобно использовать для движения по массивам, задавая в bx номер элемента в массиве. - Адресация по базе с индексированием (допустимы BX + SI, BX + DI, BP + SI, BP + DI). Используется для движения по матрице. Равноценные варианты записи:
mov ax, [bx+si+2]
mov ax, [bx+2][si]
mov ax, 2[bx][si]
mov ax, [bx][si]+2
mov ax, [bx][si+2]
16 битов - отдельные флажки.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CF - PF - AF - ZF SF TF IF DF OF IOPL NT -
- CF (carry flag) - флаг переноса (при выходе за рязрядную сетку)
- PF (parity flag) - флаг чётности
- AF (auxiliary carry flag) - вспомогательный флаг переноса
- ZF (zero flag) - флаг нуля
- SF (sign flag) - флаг знака
- TF (trap flag) - флаг трассировки
- IF (interrupt enable flag) - флаг разрешения прерываний
- DF (direction flag) - флаг направления
- OF (overflow flag) - флаг переполнения (изменение знакового разряда)
- IOPL (I/O privilege flag) (появился в 286 процессоре) - уровень приоритета ввода-вывода
- NT (nested task) (появился в 286 процессоре) - флаг вложенности задач
CMP <приёмник>, <источник>
- Источник - число, регистр или переменная
- Приёмник - регистр или переменная; не может быть переменной одновременно с источником
- Вычитает источник из приёмника, результат никуда не сохраняется (в отличие от команды
SUB
), а выставляются флаги CF, PF, AF, ZF, SF, OF
- Переход типа
short
илиnear
- Обычно используются в паре с CMP
- Термины “выше” и “ниже” - при сравнении беззнаковых чисел
- Термины “больше” и “меньше” - при сравнении чисел со знаком
Команда | Описание | Состояние флагов для выполнения перехода |
---|---|---|
JO | Есть переполнение | OF = 1 |
JNO | Есть переполнения | OF = 0 |
JS | Есть знак | SF = 1 |
JNS | Нет знака | SF = 0 |
JE, JZ | Если равно/если ноль | ZF = 1 |
JNE, JNZ | Не равно/не ноль | ZF = 0 |
JP/JPE | Есть чётность / чётное | PF = 1 |
JNP/JPO | Нет чётности / нечётное | PF = 0 |
JCXZ | CX = 0 | - |
Команда | Описание | Состояние флагов для выполнения перехода | Знаковый |
---|---|---|---|
JB JNAE JC |
Если ниже Если не выше и не равно Если перенос |
CF = 1 | Нет |
JNB JAE JNC |
Если не ниже Если выше или равно Если нет переноса |
CF = 0 | Нет |
JBE JNA |
Если ниже или равно Если не выше |
CF = 1 или ZF = 1 | Нет |
JA JNBE |
Если выше Если не ниже и не равно |
CF = 0 и ZF = 0 | Нет |
Команда | Описание | Состояние флагов для выполнения перехода | Знаковый |
---|---|---|---|
JL JNGE |
Если меньше Если не больше и не равно |
SF <> OF | Да |
JGE JNL |
Если больше или равно Если не меньше |
SF = OF | Да |
JLE JNG |
Если меньше или равно Если не больше |
ZF = 1 или SF <> OF | Да |
JG JNLE |
Если больше Если не меньше и не равно |
ZF = 0 и SF = OF | Да |
TEST <приёмник>, <источник>
- Логическое умножение
- Аналог AND, но результат не сохраняется.
- Выставляются флаги SF, ZF, PF.
Прерывание - особая ситуация, когда выполнение текущей программы приостанавливается и управление передаётся программе-обработчику возникшего прерывания.
Виды прерываний:
- аппаратные (асинхронные) - события от внешних устройств;
- внутренние (синхронные) - события в самом процессоре, например, деление на ноль;
- программные - вызванные командой INT
Аналог системного вызова в современных ОС.
Используется наподобие вызова подпрограммы.
Номер функции передаётся через AH.
Функция | Назначение | Вход | Выход |
---|---|---|---|
02 | Вывод символа в stdout | DL = ASCII-код символа | - |
09 | Вывод строки в stdout | DS:DX - адрес строки, заканчивающейся символом $ | - |
Функция | Назначение | Вход | Выход |
---|---|---|---|
01 | Считать символ из stdin с эхом | - | AL - ASCII-код символа |
06 | Считать символ без эха, без ожидания, без проверки на Ctrl+Break | DL = FF | - |
07 | Считать символ без эха, с ожиданием и без проверки на Ctrl+Break | - | - |
08 | Считать символ без эха | - | - |
10 (0Ah) | Считать строку с stdin в буфер | DS:DX - адрес буфера | Введённая строка помещается в буфер |
0Bh | Проверка состояния клавиатуры | - | AL=0, если клавиша не была нажата, и FF, если была |
0Ch | Очистить буфер и считать символ | AL=01, 06, 07, 08, 0Ah | - |