Реален режим
Реален режим (на английски: real mode) е режим на работа на компютърните процесори в архитектурата x86. Всеки x86 процесор влиза в реален режим веднага след включване на захранването му. При реалния режим, максималната адресирана памет е 1 MB (220 байта) и няма апаратна защита на достъпа до паметта.
История
[редактиране | редактиране на кода]Първите процесори от фамилията x86 са 16-битови и могат да работят единствено в реален режим. Всъщност понятието реален режим се появява значително по-късно, когато е въведен защитеният режим.
Въпреки че при появата си процесора Intel 8086 е най-съвременният 16-битов процесор, с времето недостатъците на архитектурата му започват да пречат на развитието на софтуера за персонални компютри. Основните ограничения на 8086 (и съответно на реалния режим) са малкото адресно пространство и липсата на апаратна защита на паметта от злонамерени или дефектни програми.
Технология
[редактиране | редактиране на кода]Реалният режим на работа се характеризира със следните архитектурни особености:
- 14 16-битови регистъра, от които 8 са с общо предназначение.
- 1 MB (220 байта) адресно пространство.
- 64 KB (216 байта) входно-изходно адресно пространство.
- Фиксиран размер на сегмента на паметта – 64 KB (216 байта)
- 7 типа данни.
- 9 метода за адресиране.
- Над 80 машинни инструкции
Трябва да се има предвид, че горепосочените особености са в сила само за „чистия“ реален режим – т.е. този, който е напълно обратно съвместим с 16-битовите x86 процесори: 8086 и 80186 на Intel. При 32-битовите процесори от x86 фамилията дори в реален режим е възможен достъпът до пълния 32-битов размер на регистрите, както и допълнителни типове данни и методи за адресиране. Ако тези разширения бъдат използвани, то програмата няма да е обратно съвместима с 16-битовите x86 процесори.
Регистри
[редактиране | редактиране на кода]В реален режим всеки x86 процесор има достъп до 14 16-битови регистъра. Осем от тях (AX, BX, CX, DX, SP, BP, SI и DI) са регистри с общо предназначение. Въпреки това, всеки от тях си има свои специфични функции (например достъпът до AX става най-бързо и с най-къса машинна инструкция, а CX се използва за брояч при цикли). Всеки от регистрите AX, BX, CX и DX може да бъде разглеждан и като 2 8-битови регистъра, до които има независим достъп (напр. горните 8 бита на DX са 8-битов регистър с името DH, а долните 8-бита – 8-битов регистър с името DL).
Регистрите SP и BP се използват при работата със стека, като първият е указателят на стека, а вторият обикновено се използва от езиците на високо ниво за формирането на така наречения стек фрейм (stack frame) на процедурите. Регистрите SI и DI се използват при формирането на адреса при някои инструкции (най-вече при операции със низове).
Други 4 16-битови регистъри са сегментните регистри CS, DS, ES и SS, които се използват при формирането на адресите. Регистърът FLAGS съдържа еднобитови флагове, които отразяват текущото състояне на процесора и събития като препълване, пренос към по-старши разред, нулев резултат и т.н. Последният регистър е програмният брояч IP, който съдържа адреса на следващата инструкция, която трябва да бъде изпълнена от процесора.
Типове данни
[редактиране | редактиране на кода]В реален режим x86 процесорът може да обработва следните типове данни:
- Цели числа без знак. Могат да бъдат 8-битови (байт) или 16-битови (дума). Байтът има диапазон на възможните стойности от 0 до 255 (28 – 1), а думата – от 0 до 65536 (216 – 1).
- Цели числа със знак. Могат да бъдат 8-битови или 16-битови, в допълнително кодиране (най-старшият бит е знаков). 8-битовите имат диапазон на възможните стойности от -128 до 127, а 16-битовите – от -32768 до 32767.
- Двоично-десетични (BCD) числа. Имат две разновидности – пакетирани и непакетирани. При непакетираните BCD числа във всеки байт от числото се съдържа една десетична цифра. При пакетираните BCD числа във всеки байт са пакетирани 2 десетични цифри (едната в младшите 4 бита, а другата – в старшите 4 бита).
- низ от байтове. Последователност от байтове с максимален размер до 65535 (216 – 1) байта.
Методи за адресиране
[редактиране | редактиране на кода]Повечето x86 инструкции са двуадресни (т.е. работят върху 2 операнда). Първият операнд е както първия източник, така и вместилище за резултата от операцията, а вторият операнд е вторият източник.
Операндите може да се намират в паметта, в регистър (обикновено някой от регистрите с общо предназначение), или да са зададени като непосредствена стойност, която е закодирана в самата инструкция. В повечето случаи е допустимо само единият операнд да е разположен в паметта или да е непосредствен (закодиран директно в инструкцията).
Когато единият операнд е разположен в паметта, адресът му се определя по следната формула:
A = B + I + O,
където:
A е полученият ефективен адрес на операнда,
B е базов адрес (задава се в регистър BX или BP),
I е индекс (задава се в регистър SI или DI),
O е отместване, което е непосредствено закодирано в самата инструкция като 8- или 16-битово число със знак.
Трябва да се има предвид, че полученият по този начин 16-битов адрес, всъщност представлява отместване в рамките на подразбиращия се сегмент в паметта. Началният адрес на сегмента се получава като се умножи по 16 (т.е. като се измести няляво с 4 разреда) съдържанието на съответния сегментен регистър (CS, DS, SS, ES). Крайният физически адрес на данните в паметта се получава като се събере началният адрес на сегмента с полученото по горната формула отместване.
Кой точно сегментен регистър се използва при изчисляването на адреса зависи от вида на зарежданите данни: CS се използва за инструкциите, DS – за данните, SS – за стека, а ES – при някои инструкции за работа с низове. В повечето случаи е възможно подразбиращият се сегментен регистър да бъде променен с префикс на машинната инструкция.
Сегментната организация на паметта в реалния режим се използва единствено за да е възможно адресирането на 1 MB памет от 16-битов процесор. От гледна точка на процесора сегментите винаги са дълги 64 KB и няма начин да бъде ограничен достъпът до някои части от паметта.
Поради описаната сегментна организация на паметта, се използват два вида указатели: 16-битови (наричани близки – near) и 32-битови (наричани дачечни – far). Близките указатели представляват отместване в рамките на един сегмент, а далечните указатели се състоят от 16-битов начален адрес на сегмента (който се зарежда в съответния сегментен регистър) и 16-битово отместване в рамките на сегмента.
За разлика от други процесорни архитектури, в x86 е възможно адресирането на думи, намиращи се на произволен адрес. Все пак, когато адресът не е кратен на размера на думата, е възможно достъпът да е по-бавен.
Входно-изходно адресно пространство
[редактиране | редактиране на кода]При x86 архитектурата могат да се използват и двата основни начина за връзка с входно-изходните устройства на компютъра – вмъкване в основното адресно пространство и използването на специално входно-изходно адресно пространство.
Входно-изходното адресно пространство е с размер 64 KB (216 байта) и достъпът до него става с помощта на специални инструкции (IN, OUT). Методите на адресиране, които се използват от тези инструкции, са: непосредствено задаване на адреса в инструкцията или задаване на адреса в регистрите AL или AX. Когато адресът е в първите 256 байта от входно-изходното адресно пространство, може да се използва 8-битов адрес вместо 16-битов.
Инструкции
[редактиране | редактиране на кода]Инструкциите на x86 са сложни и гъвкави (x86 е CISC архитектура). Инструкциите в реален режим са основният вид инструкции, които се използват в програмите за тази архитектура (тези инструкции са достъпни и в защитен режим, но с повече типове данни и методи на адресиране). Инструкциите може да се разделят условно на няколко групи.
Инструкции за трансфер на данни
[редактиране | редактиране на кода]- MOV – копиране на данни от първия във втория операнд. (Поне единият трябва да е регистър)
- PUSH – записване на данни в стека и декрементиране на стековия указател.
- POP – четене на данни от стека и инкрементиране на стековия указател.
- IN, OUT – четене от и запис във входно-изходното адресно пространство.
- XCHG – размяна на съдържанието на двата операнда. (Поне единият трябва да е регистър)
- LEA – изчисляване на ефективния адрес и прехвърлянето му в регистър.
- XLAT – бърз достъп до таблици с индекс с размер до 1 байт.
Аритметични инструкции
[редактиране | редактиране на кода]- ADD, SUB – събиране и изваждане на цели числа.
- ADC, SBB – събиране и изваждане на цели числа с отчитане на преноса.
- MUL, IMUL – умножение на цели числа без и със знак.
- DIV, IDIV – делене на цели числа без и със знак.
- AAA, AAS, DAA, DAS, AAM, AAD – специализирани инструкции за корекции на резултата след аритметична операциия с BCD числа.
- NEG – смяна на знака на цяло число.
- INC – увеличаване с 1 на цяло число.
- DEC – намаляване с 1 на цяло число.
- CBW – разширяване на 8-битово число със знак в 16-битово.
- CWD – разширяване на 16-битово число със знак в 32-битово.
- CMP – сравняване на цели числа.
Логически инструкции
[редактиране | редактиране на кода]- AND, OR, NOT, XOR – побитови логически операции.
- ROL, ROR, SAL, SAR, SHL, SHR – аритметични и логически побитови измествания.
- TEST – побитово сравнение.
Инструкции за работа с низове
[редактиране | редактиране на кода]- CMPS – сравнение на низове.
- SCAS – сравнение на низ с регистър.
- MOVS – трансфер на низ от паметта на друго място в паметта.
- LODS – прехвърляне от низ в регистър.
- STOS – прехвърляне от регистър в низ.
- REP, REPE/REPZ, REPNE/REPNZ – префикси, които се използват заедно с инструкциите за работа с низове.
Инструкции за преход
[редактиране | редактиране на кода]- JMP – безусловен преход.
- JO, JNE, JB/JNAE/JC, JNB/JAE/JNC, JE/JZ, JNE/JNZ, JBE/JNA, JS, JNS, JP/JPE, JNP/JPO, JL/JNGE, JNL/JGE, JLE/JNG, JNLE/JG – условен преход (в зависимост от съдържанието на регистър FLAGS).
- CALL – извикване на подпрограма.
- RET – връщане от подпрограма. (RETF ако програмата е извикана чрез Сегмент и Отместване)
- LOOP – безусловен преход в рамките на цикъл.
- LOOPE/LOOPZ, LOOPNE/LOOPNZ – условен преход в рамките на цикъл.
Други инструкции
[редактиране | редактиране на кода]- INT, INT3, INTO – предизвикване на прекъсване.
- IRET – връщане от подпрограма за обработка на прекъсване.
- BOUND – проверка за нарушаване на границите на масив.
- SAHF, LAHF – прехвърляне на младшия байт на FLAGS във и от AH.
- PUSHF, POPF – запис и четене на FLAGS във и от стека.
- CLC, STC, CMC, CLD, STD, CLI, STI – нулиране и установяване на различни флагове във FLAGS.
- HLT – спиране на процесора.
- WAIT – чакане на копроцесор.
- NOP – празна инструкция.
Проблеми
[редактиране | редактиране на кода]Както вече беше споменато, при създаването си, x86 архитектурата (която тогава е еквилалентна на сегашния реален режим) е много авангардна. За пръв път се използва сегментна организация на паметта (макар и доста ограничена) в микропроцесор. Регистрите са много повече от тези на тогавашните микропроцесори, методите за адресиране и инструкциите са гъвкави и разнообразни.
С течение на времето обаче, 16-битовият реален режим става все „по-тесен“ на съществуващите операционни системи и приложни програми по следните причини:
- Ограничението от 1 MB адресно пространство е твърде малко в сравниение с нарастващите нужди на приложните програми.
- Липсата на апаратна защита на паметта води до ниска стабилност и сигурност на операционните системи, които изключително лесно могат да бъдат блокирани и повредени от зле работещи или злонамерени програми (компютърни вируси).
- 16-битовият размер на машинната дума е твърде малък и често се налага обработката на големите числа с няколко инструкции, което значително забавя изпълнението на програмния код.
Всички тези проблеми бяха решени с разширяването на машинната дума до 32 бита и въвеждането на т.нар. защитен режим (protected mode).
Приложения
[редактиране | редактиране на кода]Изключително популярната в миналото операционна система DOS работи почти изцяло в реален режим. Първите версии на операционната система Windows (Windows 1.0 и Windows 2.0) също използваха реалния режим на работа.
В наши дни реалният режим се използва изключително рядко – най-вече в секторите за начално зареждане. Всички съвременни операционни системи и приложни програми използват защитения режим.
Вижте също
[редактиране | редактиране на кода]Външни препратки
[редактиране | редактиране на кода]- Списък с инструкциите на процесорите Intel 8086/80186/80286/386/486[неработеща препратка]
- The Intel Architecture Software Developer’s Manual, Volume 1: Basic Architecture
- The Intel Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference
- The Intel Architecture Software Developer’s Manual, Volume 3: System Programming