Процессор имеет байтовую адресацию и поддерживает сегментную адресацию . Сегмент - адресное пространство .
Пример адреса сегмента :
DS : FF79H
В следующем примере кодовый регистр указывает на то , что адрес сегмента кода лежит в другом регистре :
CS : EIP
Исключение - событие , происходяшее в случае ошибки , например при делении на ноль .
Некоторые исключения генерируют код ошибки , например
$PF(fault code)
История интела начинается с 8086 в 1978 г. У него 16-битные регистры и шина , с 20-битной адресацией
дающие 1 метр адресного пространства . Его 4 сегментных регистра в состоянии запомнить 20-битный адрес
текущего сегментного регистра . Это real mode - процессор .
286 был первым процессором с защищенным режимом . Дескрипторы обеспечивают уже 24-битную адресацию ,
адресное пространство выросло до 16 метров , появилась виртуальная память . Появились 4 уровня защиты
операционной системы . Появились TS(task switch) и LDT(local descriptor tables).
386 процессор имеет уже 32-разрядные регистры . Адресация теперь 32-битная , дающая 4 гига адресного
пространства . Появился пэйджинг с 4-кб страницей для управления виртуальной памятью .
Сегменты теперь ничем не ограничены - вернее , 4 гигами . 386 имеет 6 параллельных блоков :
Base Interfsce Unit
Code Prefetch Unit
Instruction Decode Unit
Execution Unit
Segment Unit
Paging Unit
В 486 с появлением суперскалярной архитектуры , некоторые инструкции могут распараллеливаться и выполняться
за 1 такт . В 486 добавлен мат. процессор .
На мульти-процессорных системах добавлен Advanced Programmable Interrupt Controller - APIC , и появился
специальный режим - dual processing .
Intel Pentium Pro имеет 3-суперскаляоную архитектуру , т.е. может выполнять 3 инструкции за 1 такт .
В нем имеется 8 кб кэша 1 уровня и 256 кб кэща 2 уровня .
Режимы 386
386 поддерживает 3 режима :
1 защищенный - protected mode
2 реальный - real-address mode
3 системный - system management vmode
386 имеет следующие ресурсы :
1 память - 2^32
2 8 регистров данных на 32 бита
3 6 сегментных регистров на 16 бит
4 контрольный регистр EFLAGS - 32 бита
5 регистр статуса EIP - 32 бита
6 стэк
Память разбита на байты . Каждый байт имеет уникальный адрес , который называется физическим адресом .
Память простирается до 4 гиг - 2 ^32 .
Для облегчения работы с памятью придумали сегментацию и пэйджинг .
Программы не работают с памятью напрямую . Для работы имеются 3 модели работы с памятью :
1 flat
2 segment
3 real address
При flat модели всё - и код, и данные,истек - располагаются в едином линейном адресном пространстве.
Любой адрес здесь - это прямой линейный адрес .
При segment модели код,данные,стек разбиты по разным сегментам . Здесь уже нет прямого линейного адреса-
он заменен на логический,который состоит из сегментного селектора и смещения .
Таких сегментов может быть более 16000 , причем размер сегмента неограничен. Сегментация памяти - это
прежде всего надежность при разбиении данных,кода и стэка .
В real-address режиме вся память разделена на сегменты по 64 кб . Максимальный размер памяти здесь - 2^20 .
Как взаимодействуют режимы процессора с режимами памяти ?
Защищенный режим процессора может использовать любую модель памяти .
Реальный режим процессора работает только с реальным режимом памяти.
Если размер адреса или операнда 32-битный , доступна память размером 2^32 .
Если размер адреса или операнда 16-битный , доступна память размером 2^16 .
При 32-битной адресации сегментный селектор - 16-битный , смещение - 32-битное .
При 16-битной адресации все 16-битное .
Регистры данных :
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP - 32-битные .
В этой группе особняком стоит ESP - это указатель стека . Его нельзя использовать более ни для чего,
в то время как остальные 7 можно использовать произвольным образом .
EAX - аккумулятор для операндов
EBX - указатель на дата-сегмент
ECX - счетчик
Сегментные регистры :
CS,DS,SS,ES,FS,GS
В них хранятся селекторы - указатели на сегменты памяти .
В CS хранится адрес кодового сегмента . Он складывается с адресом , который лежит в регистре EIP .
DS,ES,FS,GS - хранятся адреса сегментов данных . Данные могут быть расшаренными,наследуемыми и т.д.
SS - адрес сегмента стэков . В приложении может быть создано множество стэков , и SS может быть загружен
явно , в отличие от CS .
EFLAGS регистр - включает контрольный флаг , группу статус-флагов , группу системных флагов .
Биты 1,3,5,15,22-31 зарезервированы .
Некоторые флаги в нем могут быть модифицированы .
Следующие команды позволяют обмен между стеком и отдельными битами этого регистра :
LAHF,SAHF,PUSHF,PUSHFD,POPF,POPFD .
Флаги могут быть модифицированы с использованием инструкций :
BT,BTS,BTR,BTC.
При мультизадачности , процессор автоматически записывает флаговый регистр для каждой задачи в специальный
сегмент памяти - task state segment - TSS .
Статус-флаги - это 1,2,4,6,7,11 - они изменяются в рез-те арифметических инструкций ADD,SUB,MUL,DIV .
Direction-флаг - это 10 - предназначен для строковых команд MOVS,CMPS,SCAS,LODS,STOS .Операция STD устанавливает
DF в 1 , операция CLD - в 0 .
Системные флаги - 9(IF),8(TF),12,13(IOPL),14(NT),16(RF),17(VM),18(AC),19(VIF),20(VIP),21(ID)
Их нельзя модифицировать из пользовательских программ .
Регистр EIP - в нем хранится адрес операции , которая будет выполняться следующей . Это то самое смещение ,
добавляемое к сегментному регистру . Его значение нельзя изменить , можно только прочитать путем вызова
call и прочитать возвращаемое значение из процедурного стека .
Каждый кодовый сегмент имеет 2 атрибута , которые зависят от флага D в регистре CS . Если D=1 ,
то эти атрибуты - 32-битные , если D=0 , то они 16-битные .
Процедуры,прерывания,исключения .
386 может вызывать процедуры 2 путями
1 CALL , RET
2 ENTER , LEAVE
Оба механизма используют процедурный стек .
Стек - это массив памяти . Стек находится всегда в стековом сегменте . Его адрес лежит в SS .
Доступная часть стека называется его вершиной . Указатель на вершину лежит в ESP .
Данные помещаются в стек командой PUSH и извлекаются POP . Стек растет вниз , т.е. при добавлении
значения в стек указатель в ESP уменьшается .
В данный момент времени всегда доступен только один текущий стек , и его адрес находится в SS .
Для того , чтобы один из многих стеков сделать текущим , нужно выполнить :
1 Установить стековый сегмент
2 Загрузить адрес стека в SS с помощью команд MOV,POP или LSS .
3 Загрузить адрес верщины стека в ESP
всё теми же команд MOV,POP или LSS .
Стек обычно разделен на фреймы - локальные переменные , параметры процедур. Фреймами управляет регистр EBP.
При вызове CALL процедуры , ее адрес , хранимый в EIP , помещается в сек , а потом при выходе восстанавливается .
Другие процедуры могут лежать либо в этом же кодовом сегменте (near call), либо в других (far call).
Near call и far call отличаются друг от друга - во втором случае необходимо сохранять регистр CS в стеке .
Передача параметров
Передача параметров между процедурами может осуществляться 3 способами :
1 С использованием 6 основных регистров EAX,EBX,ECX,EDX,ESI,EDI
- не более 6 параметров .
При этом их содержимое нужно обязательно сохранить
в стеке или в памяти .
Можно использовать специальную команду PUSHA
для сохранения сразу всех 8 основных регистров .
Флаговый регистр по частям сохраняется
в стеке командами PUSHF , PUSHFD .
2 Через стек - неограниченное число параметров ,
нужно также толково использовать фреймы стека через EBP.
3 Через список аргументов в сегменте данных -
передается адрес этого списка.
В зависимости от уровня защиты , 0 или 3 , адрес стека и указатель на вершину стека хранятся в разных
местах . Для 3-го низкого пользовательского уровня они хранятся в SS и ESP .
Для защищенного 0-го уровня они хранятся в другом месте - в памяти , точнее в TSS .
Когда мы из пользовательской программы пытаемся вызвать системную процедуру , которая лежит
где-то совсем в другом кодовом сегменте , происходит следующее :
1 проверка прав
2 временно сохраняются SS,ESP,CS,EIP
3 грузятся новые адреса из TSS в SS и ESP
4 адреса из старой вызывающей программы сохраняются в стеке
5 параметры из вызывающей программы - в стек
6 регистры CS и EIP из старой вызывающей
программы сохраняются в стеке
7 загружаем из т.н. call gate новые адреса CS и EIP
для вызываемое процедуры более высокого уровня
8 начинаем выполнение более привелегированной программы
Назад все в обратном порядке :-)
Прерывание - асинхронное событие , возникающее на устройстве .
Исключение - синхронное событие , которое генерится процессором.
386 определяет 16 основных прерываний и 224 пользовательских прерываний ,
которые собраны в таблице IDT . Идентификатор в этой таблице называется вектором .
Инструкции ENTER и LEAVE обеспечивают вызов процедур из языков высокого уровня .
ENTER имеет 2 числовых параметра : первый указывает количество динамической памяти ,
выделяемой при вызове , второй используется для доступа к переменным из других процедур .
LEAVE возвращает управление из процедуры , вызванной с помощью ENTER.
Типы данных
Основные типы
байт
слово - 2 байта
двойное слово - 4 байта
четвертное слово - 8 байт
Дополнительные типы
целое - может быть байтом,словом или двойным словом ,
как положительное,так и отрицательное .
знак хранится в 7 , 15 или 31 бите .
BCD целое - 4-битное беззнаковое целое от 1 до 9
указатель - адрес ячейки памяти , бывают 2 типов -
ближние (32 бит) и дальние (48 бит).
ближний указатель - это 32-битное смещение
внуьтри сегмента , дальний - это 16-битный адрес
сегмента плюс 32-битное смещение внутри него
битовое поле - последовательность бит в памяти не более 32 бит .
строки - могут быть битовыми или байтовыми ,
находятся в памяти и имею неограниченный размер
Операнды
У инструкции может быть несколько операндов . Операнд может быть указан явно или неявно .
Он может быть расположен в инструкции , в регистре , в памяти , в порту .
Операнд может быть указан явно - пример : 14 явно добавляется к EAX :
ADD EAX, 14
Все арифметические операции имеют явные операнды .
Неявное представление операндов может быть выполнено с помощью регистров .
При этом операнд может занять не один , а пару регистров .
Указатель на сегмент может быть определен как явно , так и неявно . Наиболее простой способ-
загрузить селектор в сегментный регистр . Когда происходит загрузка или выгрузка данных в память ,
регистр DS является базовым по умолчанию , и в нем хранится адрес сегмента данных.
Но DS можно переназначить - для этого используется префикс ":" , например
MOV ES:[EBX],EAX
в этом примере содержимое EAX копируется в память в сегмент данных , адрес которого указан в ES ,
и смещение находится в регистре EBX .
Адрес состоит из 16-битного адреса сегмента + 32 битное смещение . Смещение может задаваться
явно(displacement) или вычисляться(effective address) , которое может быть как положительным ,
так и отрицательным .
Использование базового адреса в комбинации со смещением может использоваться например для
индексации массива или доступа к полю структуры . Использование комбинации из 2-х регистров
в качестве базового может использоваться для доступа к 2-мерному массиву .
386 поддерживает 65536 8-битных портов .
Обзор инструкций
В 386 принято разбивать инструкции на 3 больших группы :
целочисленные
с плавающей точкой
системные .
Целочисленные инструкции делятся на арифметические,логические и программные.
Целочисленные :
Копирование данных
MOV - безусловное
CMOVE - условное
CMOVNE
CMOVA
CMOVAE
CMOVB
...
CMOVNP
XCHG - обмен операндами
BSWAP - байт-свопинг
XADD - обмен + add
CMPXCHG - сравнение и обмен
IN - чтение из порта
OUT - запись в порт
CWD - конвертация слова в двойное слово
CBW - конвертация байта в слово
Арифметические инструкции
ADD Integer add
ADC Add with carry
SUB Subtract
SBB Subtract with borrow
IMUL Signed multiply
MUL Unsigned multiply
IDIV Signed divide
DIV Unsigned divide
INC Increment
DEC Decrement
NEG Negate
CMP Compare
Десятичная арифметика
DAA Decimal adjust after addition
DAS Decimal adjust after subtraction
AAA ASCII adjust after addition
AAS ASCII adjust after subtraction
AAM ASCII adjust after multiplication
AAD ASCII adjust before division
Логические инструкции
AND And
OR Or
XOR Exclusive or
NOT Not
Сдвиг и ротация
SAR Shift arithmetic right
SHR Shift logical right
SAL/SHL Shift arithmetic left/Shift logical left
SHRD Shift right double
SHLD Shift left double
ROR Rotate right
ROL Rotate left
RCR Rotate through carry right
RCL Rotate through carry left
Битовые байтовые инструкции
BT Bit test
BTS Bit test and set
BTR Bit test and reset
BTC Bit test and complement
BSF Bit scan forward
BSR Bit scan reverse
SETE/SETZ Set byte if equal/Set byte if zero
SETNE/SETNZ Set byte if not equal/Set byte if not zero
TEST Logical compare
Инструкции перехода
JMP Jump
JE/JZ Jump if equal/Jump if zero
JNE/JNZ Jump if not equal/Jump if not zero
JA/JNBE Jump if above/Jump if not below or equal
JAE/JNB Jump if above or equal/Jump if not below
JB/JNAE Jump if below/Jump if not above or equal
JBE/JNA Jump if below or equal/Jump if not above
JG/JNLE Jump if greater/Jump if not less or equal
JGE/JNL Jump if greater or equal/Jump if not less
JL/JNGE Jump if less/Jump if not greater or equal
JLE/JNG Jump if less or equal/Jump if not greater
JC Jump if carry
JNC Jump if not carry
JO Jump if overflow
JNO Jump if not overflow
JS Jump if sign (negative)
JNS Jump if not sign (non-negative)
JPO/JNP Jump if parity odd/Jump if not parity
JPE/JP Jump if parity even/Jump if parity
JCXZ/JECXZ Jump register CX zero/Jump register ECX zero
LOOP Loop with ECX counter
LOOPZ/LOOPE Loop with ECX and zero/Loop with ECX and equal
LOOPNZ/LOOPNE Loop with ECX and not zero/Loop with ECX and not equal
CALL Call procedure
RET Return
IRET Return from interrupt
INT Software interrupt
INTO Interrupt on overflow
BOUND Detect value out of range
ENTER High-level procedure entry
LEAVE High-level procedure exit
Символььные инструкции
MOVS/MOVSB Move string/Move byte string
MOVS/MOVSW Move string/Move word string
MOVS/MOVSD Move string/Move doubleword string
CMPS/CMPSB Compare string/Compare byte string
CMPS/CMPSW Compare string/Compare word string
CMPS/CMPSD Compare string/Compare doubleword string
SCAS/SCASB Scan string/Scan byte string
SCAS/SCASW Scan string/Scan word string
SCAS/SCASD Scan string/Scan doubleword string
LODS/LODSB Load string/Load byte string
LODS/LODSW Load string/Load word string
LODS/LODSD Load string/Load doubleword string
STOS/STOSB Store string/Store byte string
STOS/STOSW Store string/Store word string
STOS/STOSD Store string/Store doubleword string
REP Repeat while ECX not zero
REPE/REPZ Repeat while equal/Repeat while zero
REPNE/REPNZ Repeat while not equal/Repeat while not zero
INS/INSB Input string from port/Input byte string from port
INS/INSW Input string from port/Input word string from port
INS/INSD Input string from port/Input doubleword string from port
OUTS/OUTSB Output string to port/Output byte string to port
OUTS/OUTSW Output string to port/Output word string to port
OUTS/OUTSD Output string to port/Output doubleword string to port
Флаговые инструкции
STC Set carry flag
CLC Clear the carry flag
CMC Complement the carry flag
CLD Clear the direction flag
STD Set direction flag
LAHF Load flags into AH register
SAHF Store AH register into flags
PUSHF/PUSHFD Push EFLAGS onto stack
POPF/POPFD Pop EFLAGS from stack
STI Set interrupt flag
CLI Clear the interrupt flag
Инструкции сегментных регистров
LDS Load far pointer using DS
LES Load far pointer using ES
LFS Load far pointer using FS
LGS Load far pointer using GS
LSS Load far pointer using SS
Разные инструкции
LEA Load effective address
NOP No operation
UB2 Undefined instruction
XLAT/XLATB Table lookup translation
CPUID Processor Identification
Системные инструкции
LGDT Load global descriptor table (GDT) register
SGDT Store global descriptor table (GDT) register
LLDT Load local descriptor table (LDT) register
SLDT Store local descriptor table (LDT) register
LTR Load task register
STR Store task register
LIDT Load interrupt descriptor table (IDT) register
SIDT Store interrupt descriptor table (IDT) register
MOV Load and store control registers
LMSW Load machine status word
SMSW Store machine status word
CLTS Clear the task-switched flag
ARPL Adjust requested privilege level
LAR Load access rights
LSL Load segment limit
VERR Verify segment for reading
VERW Verify segment for writing
MOV Load and store debug registers
INVD Invalidate cache, no writeback
WBINVD Invalidate cache, with writeback
INVLPG Invalidate TLB Entry
LOCK (prefix) Lock Bus
HLT Halt processor
RSM Return from system management mode (SSM)
RDMSR Read model-specific register
WRMSR Write model-specific register
RDPMC Read performance monitoring counters
RDTSC Read time stamp counter
Формат инструкций.
Инструкция MOV копирует данные между памятью и регистрами или между регистрами .
Она не может копировать данные между 2-мя ячейками памяти или между 2-мя сегментными регистрами .
Memory-to-memory может быть вызвано с помощью команды MOVS .
CMOV - условное копирование из памяти в основной
регистр или обратно .
BSWAP - побайтовая конвертация операнда ,
применяется для конвертации "big-endian" и "little endian" форматов .
XADD - делает своп 2-х операндов и их сумму пишет в destination .
PUSH - записывает в стек . Операндом может быть как содержимое памяти,
так и регистра , в том числе сегментного .
PUSHA - пишет в стек содержимое 8 основных регистров .
JMP - операция безусловного перехода , которая указывает
либо на относительный адрес , либо на
абсолютный . В первом случае операнд команды - это смещение,
которое добавляется к адресу в EIP .
CALL - вызов процедуры , операнд аналогичен , как и у JMP .
LOOP,LOOPE,LOOPZ,LOOPNE,LOOPNZ - операторы цикла , используют ECX
в качестве счетчика .
MOVS,CMPS,SCAS,LODS,STOS - инструкции копирования строк .
Имеются 2 операнда - source(ESI)и destination(EDI),
адреса которых абсолютные . По умолчанию ESI привязан к DS , но может быть
переназначен на CS, SS, ES, FS, GS . EDI привязан только к ES .
У инструкции MOVS имеются
несколько форматов - MOVSB (byte), MOVSW (word),MOVSD(dword).
LODS - загружает строку , адрес которой находится
в памяти по адресу в ESI , в регистр EAX.
STOS - выполняет операцию , обратную LODS .
REP - инструкция , позволяющая работать со строками ,
длина которых больше чем dword . Организует
цикл , при котором значения ESI и EDI изменяются
автоматически до тех пор , пока ECX != 0 .
IN,INS,OUT,OUTS - обмен данными между портами , с одной стороны ,
и регистрами или памятью , с другой .
Input / Output
Порты I/O созданы для контроля устройств периферии или перенаправления данных .
Порт может быть input , output , или и тем и другим одновременно .
К портам можно иметь доступ 2-мя путями : напрямую и через маппинг .
Имеется 64 КБ 8-битных адресов.2 последовательных 8-битных порта могут быть обьединены в один 16-битный,
или 4 в 32-битный. Для маппированных портов , любая инструкция , имеющая в качестве операнда адрес
памяти , может обращаться к таким портам . Например , MOV может обменивать данные между регистром
и мап-портом .
IN,OUT - копируют данные между портом и EAX .
Номер порта может быть явным либо в DX .
INS,OUTS - копируют данные между портом и памятью .
Номер порта - в DX , адрес памяти - в DS:ESI или ES:EDI .
В защищенном режиме , контроль за портами отслеживается в EFLAGS , TSS .
|