Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Linux Kernel 2.6...5175 
 Trees...951 
 Максвелл 3...877 
 Go Web ...832 
 William Gropp...816 
 Ethreal 3...792 
 Gary V.Vaughan-> Libtool...782 
 Ethreal 4...776 
 Rodriguez 6...772 
 Ext4 FS...766 
 Clickhouse...765 
 Steve Pate 1...762 
 Ethreal 1...747 
 Secure Programming for Li...737 
 C++ Patterns 3...724 
 Ulrich Drepper...706 
 Assembler...699 
 DevFS...670 
 Стивенс 9...657 
 MySQL & PosgreSQL...639 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org
Процессор имеет байтовую адресацию и поддерживает сегментную адресацию . Сегмент - адресное пространство . Пример адреса сегмента :
  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 .
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье