
- •Конспект лекций по ассемблеру
- •Структурная схема эвм
- •Организация памяти
- •Порты ввода/вывода
- •Сегментация памяти
- •Логические и физические адреса памяти
- •Адресация команд
- •Адресация данных
- •Адресация сегмента стека
- •Перемещаемые программы
- •Структура микропроцессора
- •Назначение регистров микропроцессора
- •Регистр флагов
- •Ассемблер
- •Выражения
- •Структура машинного оператора
- •Директивы ассемблера
- •Директивы определения данных
- •Определение слова
- •Команды и способы адресации операндов
- •Режимы адресации
- •Команда сложения add
- •Команда сложения с переносом adc
- •Команда вычитания sub
- •Imul – команда умножения со знаком
- •Idiv – команда деления со знаком
- •Команда сравнения cmp
- •Команды безусловного перехода jmp
- •1. Короткий относительный переход
- •2. Внутрисегментный переход
- •Команды условных переходов
- •Знаковые
- •Беззнаковые
- •Специальные
- •Способы адресации
- •Двухоперандные команды
- •Косвенная адресация
- •Регистровая адресация
- •Прямая адресация с индексированием
- •Прямая адресация с базированием
- •Адресация по сумме d8 и индексный регистр
- •Адресация по сумме базового регистра и смещения
- •Адресация с базированием и индексированием
- •Прямая адресация с базированием и индексированием
- •Двухоперандная команда, в которой второй операнд непосредственный
- •Формат двухоперандных команд с акумулятором и но
- •Форматы команды inc
- •Форматы команд pop и push
- •Однобайтные команды без операндов
- •Команды передачи данных mov
- •Команда обмена xchg
- •Команда загрузки исполнительного адреса lea
- •Команды управления циклами команда цикла loop
- •Команды переходов loopz, loope
- •Команды вызова подпрограмм call
- •Структура подпрограммы
- •Команды возврата
- •Передача параметров в процедуру
- •Примеры на обработку матрицы
- •Функции ввода/вывода
- •Функция вызова команды int 21h
- •Вывод на экран дисплея
- •Ввод с клавиатуры
- •Процедура ввода числа форматом слово
Адресация команд
Для адресации команд в процессоре предусмотрен регистр IP (Instruction pointer) - указатель команд или счетчик команд, который содержит адрес выбираемой из памяти команды. Данный адрес является относительным, то есть является смещением относительно начала сегмента.
┌───────┐
┌───────────────────┤ 043Dh │ <- CS
IP V └───────┘
0h ┌────────┐1 команда
1h ├────────┼────────┬────────┐2 команда
4h ├────────┼────────┼────────┘3 команда
6h ├────────┼────────┼────────┬────────┐4 команда
├────────┼────────┴────────┴────────┘
При запуске программы IP = 0, значение CS:IP = 043D:0000 – логический адрес. Это адрес первой команды программы, его называют точкой входа или стартовым адресом. Регистр IP принимает значение 0 только в случае, если первая команда программы расположена вначале сегмента кода. Вычислим физический адрес 4 команды
0 4 3 D CS
+
6 IP
------------
0 4 3 D 6 – физический адрес команды.
При естественном порядке следования команд, счетчик команд наращивается после выборки текущей команды на число, равное длине команды. После выборки 4 команды IP:=IP +4.
Для общего случая IP:=IP + n ,где n = 1 – 6, т.к команды базовой машины имеют длину от одного до 6 байт.
При выполнении команд управления осуществляется изменение IP, а в некоторых случаях и CS таким образом, чтобы CS:IP определял адрес команды перехода.
Адресация данных
Команды могут одновременно обращаться к двум сегментам данных, адреса которых находятся в регистрах DS и ES. Исполнительный адрес вычисляется аналогично, например:
1 8 7 6 ES
+
4 3 7 8 смещение
------------
1 C A D 8 – физический адрес
Смещение в данном случае может находиться в одном из регистров процессора или непосредственно в формате команды, или же вычисляется как сумма нескольких чисел.
Адресация сегмента стека
Стек организован по принципу LIFO – Last in, First out.
Процессор управляет моделью стека, так как он организован в оперативной памяти с произвольной выборкой. На рис. представлен сегмент стека, расположенный в памяти с начального адреса 3F430h и занимающий 64 байта. В регистре SS записан адрес сегмента, а в регистре SP - смещение адреса вершины стека. Когда стек пустой, физический адрес равен:
3 F 4 3 SS
+
0 0 4 0 SP
---------------
3 F 4 7 0 .
Этот адрес указывает на первое слово, лежащее за пределами сегмента стека:
┌───────┐
┌───────────────────┤ 3F43h │ <-SS
V └───────┘
Физический
адрес ┌────────┐
├────────┤
3F430 ├────────┤ ─┐
3F432 ├────────┤ │
3F434 ├────────┤ │
├────────┤ │
│ │ > Сегмент стека
│ │ │
│ │ │
├────────┤ │
├────────┤ │
3F470 ├────────┤ ─┘ 0040h<-(SP)
└────────┘
Запись в стек выполняются командой PUSH word, где PUSH – это мнемокод команды, который определяет операцию, word – это операнд размером слово ( 16 бит ), который может располагаться в регистре процессора или это переменная в памяти. Алгоритм команды:
- SP := SP – 2;
- вычисление физического адреса памяти и запись в него слова.
Пусть в стек загружено 3 слова, т.е. выполнена последовательность команд
PUSH 1_СЛОВО
PUSH 2_СЛОВО
PUSH 3_СЛОВО.
В этом случае первое слово лежит на дне стека, а третье слово – в вершине стека. На третье слово указывает регистр SP.
┌────────┐
3F430 ├────────┤
3F432 ├────────┤
├────────┤
│ . │
│ . │
│ . │
│ . │
3F46A ├────────┤ <- 003Ah (SP)
│3_СЛОВО │
3F46C ├────────┤
│2_СЛОВО │
3F43E ├────────┤
│1_СЛОВО │
3F470 └────────┘
Выборка из стека выполняются командой POP word, POP - это мнемокод команды, который определяет операцию, word – это операнд размером слово ( 16 бит ), который может располагаться в регистре процессора или это переменная в памяти. Алгоритм команды:
- из вершины стека считывается слово;
- SP:=SP+2.
Когда из стека выбрано третье слово, т.е. выполнена команда POP word, тогда SP=3Ch и указывает на второе слово. Третье слово остается в ячейке памяти с адресом 3F46A, но этот адрес – за пределами стека и программная модель стека использовать его уже не может.
После считывания из стека второго слова и первого слова, стек пустой, SP=40h. Предположим, что за тем выполняется POP word. В результате в поле word записывается слово, которое расположено за границей сегмента стека. Это слово принадлежит следующему сегменту программы. Такая ситуация является недопустимой. Будем называть ее «переполнением стека снизу».
Описанный стек рассчитан на погружение 32 слов. Пусть выполнены 32 команды PUSH word. Сегмент стека заполнен.
┌────────┐
3F430 ├────────┤ <- 0000h (SP)
3F432 │32_СЛОВО│
├────────┤
│31_СЛОВО│
├────────┤
│ . │
│ . │
│ . │
│ . │
3F46A ├────────┤
│3_СЛОВО │
3F46C ├────────┤
│2_СЛОВО │
3F43E ├────────┤
│1_СЛОВО │
3F470 └────────┘
При погружении в стек 33 слова произойдет «переполнением стека сверху».
PUSH word
1)SP:=SP-2; SP:=0000h - 2h; SP=0FFFEh
Вычисляем физический адрес.
3 F 4 3 SS
+
F F F E SP
---------------
4 F 4 2 E .
2) word->[SS:SP];
Операнд word запишется в память по физическому адресу 4F42Eh, который расположен на расстоянии 65634 от начала сегмента стека. По этому адресу может находиться другой сегмент программы, код программы будет изменен. Отметим, что такая ситуация возможна под управлением MS DOS. Операционная система WINDOWS контролирует границы программы, программа будет снята с выдачей сообщения об ошибке.
За работой стека в языках высокого уровня следит специальная система. При возникновении переполнения осуществляется прерывание программы и выдача сообщения «stack overflow». На Ассемблере такой системы нет. При необходимости ее может построить сам программист.
Для правильной работы любой программы кол-во «погружений» в стек и количество «всплытий» должно быть одинаково и первой командой должна быть команда PUSH.