- •140010, Г. Люберцы, Московской обл., Октябрьский пр-т, 403.
- •Глава 1. Архитектура реального режима
- •1.1. Память и процессор
- •Глава 1
- •Глава 1
- •1.2. Распределение адресного пространства
- •Глава 1
- •1.3. Регистры процессора
- •Глава 1
- •Глава 1
- •9 7H Шестнадцатернчное обозначение числа
- •Глава 1
- •1.4. Сегментная структура программ
- •Глава 1
- •Глава 1
- •Глава 1
- •1.5. Стек
- •Глава 1
- •1.6. Система прерываний
- •Глава 1
- •Глава I
- •1.7. Система ввода-вывода
- •Глава I
- •Глава 1
- •Глава 2. Основы программирования
- •2.1. Подготовка и отладка программы
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.2. Представление данных
- •Глава 2
- •Глава 2
- •2.3. Описание данных
- •Глава 2
- •Глава 2
- •2.4. Структуры и записи
- •Глава 2
- •Глава 2
- •2.5. Способы адресации
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.7. Вызовы подпрограмм
- •Глава 2
- •2.8. Макросредства ассемблера
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 3. Команды и алгоритмы
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •3.2. Циклы и условные переходы
- •Глава 3
- •Глава 3
- •3.3. Обработка строк
- •Глава 3
- •3.4. Использование подпрограмм
- •Глава 3
- •Глава 3
- •3.5. Двоично-десятичные числа
- •Глава 3
- •Глава 3
- •3.6. Программирование аппаратных средств
- •Глава 3
- •37Ah Порт управлсш!я
- •Глава 3
- •Глава 3
- •Глава 4. Расширенные возможности
- •4.1. Архитектурные особенности
- •Глава 4
- •4.2. Дополнительные режимы адресации
- •Глава 4
- •4.3. Использование средств 32-разрядных процессоров в программировании
- •Глава 4
- •Глава 4
- •Глава 4
- •4.4. Основы защищенного режима
- •Глава 4
- •Глава 4
- •Глава 4
- •Глава 4
- •Idiv Деление целых чисел со знаком
- •Imul Умножение целых чисел со знаком
- •In Ввод из порта
- •Inc Инкремент (увеличение на 1)
- •Int Программное прерывание
- •Into Прерывание по переполнению
- •Iret Возврат из прерывания
- •1 Lods Загрузка операнда из строки : lodsb Загрузка байта из строки lodsw Загрузка слова из строки
- •Операнд
- •Xadd память, регистр
- •Xchg Обмен данными между операндами
- •Xlat Табличная трансляция
- •Xor Логическое исключающее или
- •Содержание
Int Программное прерывание
Команда hit инициирует в процессоре процедуру прерывания, в результате которой управление передается на обработчик прерывания с номером п, который указан в качестве операнда команды int. В стек текущей программы заносится содержимое регистра флагов, сегментного регистра CS и указателя команд IP, после чего в регистры IP и CS передается содержимое двух слов из вектора прерывания с номером п (расположенных по адресам 0:п*4 и 0:п*4+2). Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, вос-станаштивает исходное состояние этих флагов.
Пример 1
int 60h
; Переход на прикладной ;обработчик прерывания 60h
Пример 2
mov AH,1
int 21h
;Функция MS-DOS — ввод с ;клавиатуры кода ASCII символа ;Вызов MS-DOS
230
Приложение
Пример 3
mov АН, О
mt 16h
;Функция BIOS (прерывание ;16h) — ввод с клавиатуры ;кода ASCII и скен-кода символа ;Вызов BIOS
Into Прерывание по переполнению
Команда into, будучи установлена вслед за какой-либо арифметической, логической или строковой командой, вызывает обработчик прерываний через вектор 4, если предшествующая команда установила флаг переполнения OF. Перед использованием команды INTO прикладной программист должен поместить в вектор прерывания 4 двухсловный адрес своей программы обработки прерывания по переполнению. Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.
Пример
add into
АХ,ВХ произвольная команда
;Вызов прикладного ;обработчика через вектор 4, ;если OF=1 ;Продолжение программы, если OF=0
Iret Возврат из прерывания
Команда iret возвращает управление прерванному в результате аппаратного или программного прерывания процессу. Команда извлекает из стека три верхние слова и помещает их в регистры IP, CS и флагов (см. команду mt). Командой iret должен завершаться любой обработчик прерываний, как аппаратных, так и программных (от команды int). Команда не воздействует на флаги, однако она загружает в регистр флагов из стека его исходное содержимое, которое было там сохранено процессором в процессе обслуживания прерывания. Если требуется, чтобы после возврата из обработчика программного прерывания командой iret какие-либо флаги процессора были установлены требуемым образом (весьма распространенный прием), их установку надо выполнить в копии флагов в стеке.
386+ IRETD
Возврат из прерывания в 32-разрядном режиме
Команда ire-td используется в защищенном режиме для возврата из обработчика прерывания или исключения, а также для переключения на исходную задачу. В отличие от 16-разрядной команды iret, данная команда, завершая обработку прерывания или исключения, снимает со стека 3 двойных слова, содержащие расширенный регистр флагов EFALGS, CS и расширенный указатель команд EIP. В случае переключения задач команда iretd выполняет переключение контекстов задач — сохранение состояния завершающейся задачи в ее сегменте состояния задачи и загрузку регистров процессора из сегмента состояния исходной задачи.
Система команд процессоров Intel
231
Jcc
Команды условных переходов
Команды,
обозначаемые (в книгах, не в программах!)
Jcc,
осуществляют
переход по указанному адресу при
выполнении условия, заданного мнемоникой
команды. Если заданное условие не
выполняется, переход не
осуществляется, а выполняется команда,
следующая за командой Jcc.
Переход
может осуществляться как вперед, так
и назад в диапазоне + 127...-128 байтов.
В составе команд процессора
предусмотрены следующие команды
условных
переходов:
ja выше
jae выше или равно
jb ниже
jbe ниже или равно
jc перенос
jcxz СХ=0
je равно
jg . больше
jge больше или равно
jl меньше
jle меньше или равно
jna не выше
jnae не выше и не равно
jnb не ниже
jnbe не ниже и не равно
jnc нет переноса
jne не равно
jng не больше
jnge не больше и не равно
jnl не меньше
jnle не меньше и не равно
jno нет переполнения
jnp нет четности
jits знаковый бит равен О
jnz не нуль
jo переполнение
jp есть четность
jpe сумма битов четная
jpo сумма битов нечетная
js знаковый бит равен
jz нуль
Условие перехода
CF=0 и ZF=0
CF=0
CF-1
CF=1 или ZF=1
CF=1
CX=0
ZF=1
ZF=0 или SF=OF
SF=OF
SF не равно OF
ZF=1 или SF не равно OF
CF=1 или ZF=1
CF=1
CF=0
CF=0 и ZF=0
CF=0
ZF=0
ZF=1 или SF не равно OF
SF не равно OF
SF=OF
ZF=0 и SF=OF
OF=0
PF=0
SF=0
ZF=0
OF=1
PF=1
PF=1
PF=0
SF=1
ZF=1
Команды условных переходов, осуществляющие переход по условию «выше — ниже», предназначены дчя анализа чисел без знака; команды, осуществляющие переход по условию «больше — меньше», предназначены для анализа чисел со знаком.
232
Приложение
Пример 1
cmp СХ,0 je equal
Пример 2
cmp AX, 10000
ja above
Пример 3
crap AX,1000h
Jg
greater
;CX=0'
;Если да, перейти на метку equal
;Пусть AX=8000h=32768
;<=-32768)
;32768 > 10000. Переход будет
;Пусть AX=8000h=-32768
;(=32768)
j-32768 < lOOOh. Перехода не будет
Пример 4
int 21h ic error
;Вызов системной функции ;Если CF=1 (ошибка), перейти ;на метку error
386+ Команды условных переходов имеют варианты 16- и 32-разрядной адресации (при тех же мнемонических обозначениях) и могут передавать управление в диапазоне -32768...+32767 байт для сегментов с атрибутом размера 16 и вдиапазоне -231...+231-1 байт для сегментов с атрибутом размера 32.
JMP Безусловный переход
Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.
Команда jmp имеет пять разновидностей:
переход прямой короткий (в пределах -128...+ 127 байтов);
переход прямой ближний (в пределах текущего программного сег мента);
переход прямой дальний (в другой программный сегмент);
переход косвенный ближний;
переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор мо- \ жет определить вид перехода по контексту, в тех же случаях, когда этой невозможно, следует использовать атрибутные операторы: ;.
short — прямой короткий переход; J
near ptr — прямой ближний переход; £-'
far ptr — прямой дальний переход; Ь
word ptr — косвенный ближний переход; ;
dword ptr — косвенный дальний переход.
устема команд процессоров Intel
2Э&
Примеры прямого короткого перехода
jmp short shpt ;Переход на метку shpt
;в пределах +127...-128 байтов
jmp shpt ;To же самое, если shpt
; находится выше по тексту программы
Примеры прямого ближнего перехода
jmp pt ;Переход на метку pt
;в пределах текущего сегмента jmp near ptr pt ;To же самое
Примеры косвенных ближних переходов
Пример 1
raov
BX,offset pt ВХ
;ВХ=адрес точки перехода ;Переход в точку-pt
Пример 2
;В полях данных:
addr dw pt
;В программном сегменте: jmp DS:addr jmp word ptr addr
Пример 3
;B полях данных:
addr dw pt
;B программном сегменте:
mov DI,offse-t addr
jmp [Dl]
Пример 4
;B полях данных: tbl dw ptl
dw pt2
dw pt3 ;B программном сегменте:
mov BX,offset tbl
mov- SI,4
call [BX][SI]
;Ячейка с адресом точки перехода
; Переход в точку pt ;То же самое
;Ячейка с адресом точки перехода
;51=адрес ячейки с адресом точки перехода ; Переход в точку pt
;Ячейка с адресом 1 ;Ячейка с адресом 2 ;Ячейка с адресом 3
;ВХ=адрес таблицы адресов переходов ;51=смещение к адресу pt3 ; Переход в точку pt3
Примеры прямых дальних переходов
jmp far ptr farpt ;Переход на метку farpt в
;другом профаммном сегменте
jmp farpt ".Переход на метку farpt в другом
программном сегменте, если farpt ;объявлена дальней меткой ;директивой farpt label far
234
Приложение
Примеры косвенных дальних переходов
Пример 1
; В полях данных:
addr dd pt ;Поле с двухсловным
;адресом точки перехода ;В профаммном сегменте:
jmp DS:addr ;Переход в точку pt
jrap dword ptr addr ;To же самое
Пример 2
;B полях данных:
addr dd pt ;Поле с двухсловным
;адресом точки перехода ;В профаммном сегменте:
mov DI,offset addr ;П1=адрес поля с адресом
;точки перехода jmp [DI] ;Переход в точку pt
386+ Допустимо использование дополнительных режимов адресации 32-разрядных процессоров. Для 32-разрядных приложений допустимо использование 32-битовых операндов. В защищенном режиме вместо сегментного адреса сегмента (при дальних переходах) выступает его селектор.
LAHF Загрузка флагов в регистр АН
Команда lahf копирует флаги SF, ZF, AF, PF и CF соответственно в разряды 7, 6, 4, 2 и 0 регистра АН. Значение битов 5, 3 и 1 регистра АН не определено. Команда не имеет параметров и не изменяет флаги процессора.
Команда lahf (совместно с командой sahf) дает возможность читать и изменять значения флагов процессора, в том числе флагов SF, ZF, AF и PF, которые нельзя изменить непосредственно. Однако следует иметь в виду, что команда lahf переносит в АН только младший байт регистра флагов. Поэтому нельзя изменить с ее помощью, например, состояние флага OF.
Пример 1
lahf
or sahf
; Регистр АН отображает ;состояние регистра флагов AH,80h ;Установка бита 1 - SF
;3афузка АН в регистр ;флагов, где теперь SF = 1
Пример 2
lahf
and sahf
; Регистр АН отображает ;состояние регистра флагов AH,OBFh ;Сброс бита 6 - ZF
;3афузка АН в регистр ;флагов, где теперь ZF = О
тем а команд процессоров Intel
235
386Р+ LAR Загрузка прав доступа
Команда lar загружает в первый операнд (16- или 32-разрядный регистр) поле атрибутов сегмента из дескриптора сегмента, заданного селектором во втором операнде. В качестве операнда с селектором может использоваться 16- или 32-разрядный регистр или ячейка памяти. В операнд-приемник поступают два байта атрибутов селектора с замаскированным полем старших битов границы сегмента,
LDS Загрузка указателя с использованием регистра DS
Команда Ids считывает из памяти по указанному адресу двойное слово (32 бит), содержащее указатель (полный адрес некоторой ячейки), и загружает младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр, а старшую половину указателя (т.е. сегментный адрес) в регистр DS. Таким образом, команда
Ids
reg,mem
эквивалентна следующей группе команд:
niov reg,word ptr mem mov DS,word ptr mem+2
В качестве первого операнда команды Ids указывается регистр общего назначения; в качестве второго — ячейка памяти с двухсловным содержимым. Указатель, содержащийся в этой ячейке, может быть адресом как процедуры, так и поля данных. Команда не воздействует на флаги процессора.
Пример 1
;В полях данных: addr dd myproc
;В программном сегменте: Ids SI,addr
Пример 2
;В полях данных: mem dw 25
addr dd myproc
;B программном сегменте: mov BX.offset addr
Ids DX,[BX]
;Двухсловный адрес процедуры ;myproc
;DS:SI ' myproc
;Ячейка памяти с произвольным содержимым Двухсловный адрес этой ;ячейки
;ВХ=адрес ячейки addr
;ВХ=смещение ячейки mem, ;В5=сегментный адрес ячейки ;mem
236
Приложение
Пример 3
;В полях данных: dptr dd proc 1
;Полный адрес процедуры
proc 2 ргосЗ
;procl
dd
;ргос!
dd
;ргос!
7В
;В программном сегменте:
mov SI,8 ;Смещение к адресу ргосЗ
Ids DI,dptr[SI] ;DS:DI -> ргосЗ
386+ Допустимо использование 32-разрядного регистра-приемника и 32-битового смещения в памяти, а также дополнительных режимов адресации 32-разрядных процессоров. В защищенном режиме вместо сегментного адреса сегмента выступает его селектор.
LEA Загрузка исполнительного адреса
Команда lea загружает в регистр, указанный в команде в качестве первого операнда, относительный адрес второго операнда (не значение операнда!). В качестве первого операнда следует указывать регистр общего назначения (не сегментный), в качестве второго — ячейку памяти. Команда
lea reg,mem эквивалентна команде
mov reg,offset mem
но у первой команды больше возможностей описания адреса интересующей нас ячейки. Команда не воздействует на флаги процессора.
Пример 1
;В полях данных: message db ;В программном сегменте: lea SI, message
Пример 2
; В полях данных:
nmb db '0123456789'
;В программном сегменте:
mov SI, 7
lea DX,nmb[SI]
Пример 3
;B полях данных:
nmb db '0123456789'
;В программном сегменте:
'Идут измерения' ;DS:SI ' message
;Смещение символа 'Т ;ОХ=адрес символа '7'
"Система команд процессоров Intel
237
mov mov lea
BX.offset msg
SI,9
SI,[BX][SI]
;Смещение символа '9' ;SI—адрес символа '9'
386+ Допустимо использование 32-битовых операндов и дополнитель-режимов адресации 32-разрядных процессоров.
386+ LEAVE Выход из процедуры высокого уровня
Команда leave выполняет действия, противоположные действиям пос-^(едней команды enter. Она логически уничтожает созданный командой enter стековый кадр со всеми содержащимися в нем локальными переменными и подготавливает стек к выполнению команды iret, завершающей переход в вызывающую процедуру. Команда leave не имеет параметров. Более подробное описание и пример см. в описании команды enter.
LES Загрузка указателя с использованием регистра ES
Команда les считывает из памяти по указанному адресу двойное слово (32 бит), содержащее указатель (полный адрес некоторой ячейки), и загружает младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр, а старшую половину указателя (т.е. сегментный адрес) в регистр ES. Таким образом, команда
les
•ивалентна следующей группе команд:
mov reg,word ptr mem mov ES,word ptr mem+2
В качестве первого операнда команды les указывается регистр общего назначения; в качестве второго — ячейка памяти с двухсловным содержимым. Указатель, содержащийся в этой ячейке, может быть адресом как процедуры, так и поля данных. Команда не воздействует на флаги процессора.
Пример 1
; В полях данных:
addr dd myproc ;Двухсловный адрес процедуры
;myproc ;В программном сегменте:
les SI,addr ;ES:SI
myproc
Пример 2
;В полях данных: mem dw 25
;Ячейка памяти с произвольным содержимым ;Двухсловный адрес этой ячейки
addr dd myproc
;В программном сегменте:
mov BX,onset addr ;ВХ=адрес ячейки addr
238
Приложение
les DX,[BX]
;ОХ=смещение ячейки mem, ;Е5=сегментный адрес ячейки mem
Пример 3
;B полях данных: dptr dd proc 1
dd proc 2
dd ргосЗ ;B программном сегменте:
mov SI, 8
les DI,dptr[SI]
;Полный адрес процедуры prod ;Полный адрес процедуры procl ;Полный адрес процедуры procl
;Смещение к адресу ргосЗ ;ES:DI -* ргосЗ
386+ Допустимо использование 32-разрядного регистра-приемника и 32-битового смещения в памяти, а также дополнительных режимов адресации 32-разрядных процессоров. В защищенном режиме вместо сегментного адреса сегмента выступает его селектор.
386+
LFS Загрузка указателя с использованием регистра FS LGS Загрузка указателя с использованием регистра FS LSS Загрузка указателя с использованием регистра FS
Команды считывают из памяти полный указатель, состоящий из селектора и 16-битового или 32-битового смещения, и загружают младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр общего назначения, а старшую половину указателя (т.е. селектор) в сегментный регистр, указанный в мнемонике команды.
В качестве первого операнда всех перечисленных команд указывается 16- или 32-разрядный регистр общего назначения; в качестве второго — ячейка памяти с 32- или 48-битовым содержимым. Команда не воздействует на флаги процессора.
Примеры см. в описании команд Ids и les.
386Р+ LGDT
Загрузка регистра таблицы глобальных дескрипторов
Команда Igdt загружает регистр таблицы глобальных дескрипторов (GDTR) из 48-битового псевдодескриптора, содержащего 32-битовый базовый адрес и 16-битовую границу таблицы глобальных дескрипторов, находящейся в памяти. В качестве операнда команды Igdt выступает относительный адрес псевдодескриптора.
386Р+ LIDT
Загрузка регистра таблицы дескрипторов прерываний
Команда lidt загружает регистр таблицы дескрипторов прерываний (IDTR) из 48-битового псевдодескриптора, содержащего 32-битовый ба зовый адрес и 16-битовую границу таблицы глобальных дескрипторов, находящейся в памяти. В качестве операнда команды lidt выступает отно сительный адрес псевдодескриптора. _
г
Система команд процессоров Intel 239
386Р+ LLDT
Загрузка регистра таблицы локальных дескрипторов
Команда lldt загружает регистр таблицы локальных дескрипторов (LDTR) селектором, определяющим таблицу дескрипторов прерываний (LDT). Селектор LDT должен входить в таблицу глобальных дескрипторов. В качестве операнда команды lldt, содержащего селектор LDT, можно использовать 16- или 32-разрядный регистр общего назначения или 16-или 32-битовое поле памяти.
386Р+ LMSW Загрузка слова состояния машины
Команда Imsw загружает в регистр слова состояния машины (так называется младшая половина управляющего регистра процессора CRO) слово состояния машины, взятое из указанного в команде операнда. В качестве операнда можно использовать 16- или 32-разрядный регистр общего назначения или 16- или 32-битовое поле памяти.
Команду Inisw можно использовать для перевода процессора из реального в защищенный режим или наоборот. В первом случае после чтения слова состояния командой smsw надо установить в нем бит 0 (бит РЕ) и загрузить назад в CRO командой Imsw. Во втором случае после после чтения слова состояния командой smsw надо сбросить в нем бит 0 и загрузить назад в CRO командой Imsw.
LOCK Запирание шины
Префикс lock, помещенный перед командой, устанавливает сигнал на линии LOCK системной шины и запрещает доступ к шине другим процессорам на время выполнения данной команды, Этот префикс предназначен для использования в многопроцессорных многозадачных системах для обеспечения исключительного доступа к памяти данного процесса (и данного процессора) на время проверки или модификации некоторой ячейки памяти. Типичный пример операций такого рода — работа с семафорами.
Если два (или более) процесса, идущие на разных процессорах, используют какой-либо общий ресурс, например, файл или лазерный диск, то необходимо обеспечить механизм, запрещающий одновременное обращение процессов к общему ресурсу. Эта задача решается с помощью семафора — ячейки памяти (байта или даже бита), состояние которого отражает доступность или, наоборот, занятость ресурса.
Если процессору понадобился общий ресурс, он читает состояние семафора и, если ресурс занят, продолжает опрашивать семафор до тех пор, пока другой процессор, использующий в настоящий момент общий ресурс, не освободит его. Обнаружив, что ресурс свободен, первый процессор устанаачивает семафор в состояние «занят» и использует ресурс. Закончив работу с ресурсом, процессор сбрасывает его семафор и дает возможность другому процессу обратиться к тому же ресурсу.
Описанный алгоритм будет работать только в том случае, если операция чтения-модификации-записи семафора будет выполняться в непре-
240
рываемом режиме. В противном случае оба процесса могут, одновременно обратившись к семафору, увидеть, что ресурс свободен, и начать его совместное использование. Избежать такой ситуации и позволяет префикс lock в сочетании с командами типа btr или bts, выполняющими комплек- 1 сные операции проверки и сброса или проверки и установки бита.
Будем считать, что семафор расположен в бите 0 байта по адресу sem, причем сброшенное состояние бита свидетельствует о занятости ресурса, а установленное состояние о том, что ресурс свободен. Тогда типичная процедура ожидания освобождения ресурса выглядит следующим образом:
mov Sl.oftset sem ;Адрес байта с семафором getsem:
lock btr byte ptr [SI],1 ;Проверка и сброс бита О
jnc getsem
Проверка состояния семафора и его модификация (запись в бит семафора 0, т.е. признака «занят») осуществляется в одной команде btr. На время выполнения этой команды шина многопроцессорной системы блокируется префиксом lock,'и другой процессор обратиться к тому же семафору не может. Блокировка шины снимается уже после того, как семафор будет переведен в состояние занятости.
Если при обращении к байту sem оказывается, что в бите семафора записан 0, т.е. ресурс занят другим процессом, команда btr сбрасывает флаг CF (путем переноса в него содержимого анализируемого бита), что приводит к многократному повторению процедуры getsem, т.е. к циклу ожидания освобождения ресурса.
Типичная процедура освобождения занятого данным процессом ресурса выглядит следующим образом:
freesem:
lock bts byte ptr [SI],1 ;Проверка и установка бита О
Собственно говоря, никакая проверка здесь не выполняется, однако процесс будет освобождать ресурс лишь если он этот ресурс использует, и проверять состояние флага в этой операции нет необходимости. Однако и здесь необходимо запирание шины на время записи в бит семафора 1, чтобы исключить одновременное обращение двух процессов к одной ячейке памяти.
386+ Префикс lock может быть использован только со следующими командами (и лишь при условии, что при их выполнении происходит обращение к памяти): adc, add, and, bt, bts, btr, btc, or, sbb, sub, xor, xchg, dec, inc, neg, not.
команд процессоров Intel 241
i