Глава 6: Основи на съвременната компютърна архитектура с асемблер

Glava 6 Osnovi Na S Vremennata Komput Rna Arhitektura S Asembler



6.1 Въведение

Съвременните компютри с общо предназначение са два вида: CISC и RISC. CISC означава Complex Instruction Set Computer. RISK означава Компютър с намален набор от инструкции. Микропроцесорите 6502 или 6510, приложими към компютъра Commodore-64, приличат повече на RISC архитектурата, отколкото на CISC архитектурата.

RISC компютрите обикновено имат по-кратки инструкции на асемблерния език (по брой байтове) в сравнение с CISC компютрите.







Забележка : Независимо дали става въпрос за CISC, RISC или стар компютър, периферното устройство започва от вътрешен порт и преминава навън през външен порт на вертикалната повърхност на системния модул на компютъра (базовия модул) и към външното устройство.



Типична инструкция на CISC компютър може да се разглежда като обединяване на няколко кратки инструкции на асемблер в една по-дълга инструкция на асемблер, което прави получената инструкция сложна. По-специално, CISC компютър зарежда операндите от паметта в регистрите на микропроцесора, извършва операция и след това съхранява резултата обратно в паметта, всичко това в една инструкция. От друга страна, това са поне три инструкции (кратки) за RISC компютъра.



Има две популярни серии компютри CISC: микропроцесорни компютри Intel и микропроцесорни компютри AMD. AMD означава Advanced Micro Devices; това е компания за производство на полупроводници. Сериите микропроцесори на Intel, по реда на развитие, са 8086, 8088, 80186, 80286, 80386, 80486, Pentium, Core, i Series, Celeron и Xeon. Инструкциите на асемблерния език за ранните микропроцесори на Intel като 8086 и 8088 не са много сложни. Те обаче са сложни за новите микропроцесори. Последните микропроцесори на AMD за серията CISC са Ryzen, Opteron, Athlon, Turion, Phenom и Sempron. Микропроцесорите Intel и AMD са известни като x86 микропроцесори.





ARM означава Advanced RISC машина. Архитектурите ARM дефинират семейство RISC процесори, които са подходящи за използване в голямо разнообразие от приложения. Докато много микропроцесори Intel и AMD се използват в настолните персонални компютри, много процесори ARM служат като вградени процесори в критични за безопасността системи като автомобилни антиблокиращи спирачки и като процесори с общо предназначение в смарт часовници, преносими телефони, таблети и преносими компютри . Въпреки че и двата типа микропроцесори могат да се видят в малки и големи устройства, RISC микропроцесорите се намират повече в малки устройства, отколкото в големи устройства.

Компютърна дума
Ако се каже, че един компютър е компютър с 32-битова дума, това означава, че информацията се съхранява, прехвърля и манипулира под формата на тридесет и две-битови двоични кодове във вътрешната част на дънната платка. Това също означава, че регистрите с общо предназначение в микропроцесора на компютъра са с ширина 32 бита. Регистрите A, X и Y на микропроцесора 6502 са регистри с общо предназначение. Те са широки осем бита и така компютърът Commodore-64 е компютър с осем битови думи.



Малко речник
X86 компютри

Значенията на байт, дума, двойна дума, четворна дума и двойна четворна дума са както следва за x86 компютрите:

  • Байт : 8 бита
  • Слово : 16 бита
  • Двойна дума : 32 бита
  • Четворна дума : 64 бита
  • Двойна четворка : 128 бита

ARM компютри
Значенията на байт, полудума, дума и двойна дума са както следва за компютрите ARM:

  • Байт : 8 бита
  • Станете наполовина : 16 бита
  • Слово : 32 бита
  • Двойна дума : 64 бита

Трябва да се отбележат разликите и приликите за имената (и стойностите) на x86 и ARM.

Забележка : Знаковите цели числа и в двата типа компютри са допълнение на две.

Местоположение на паметта
При компютъра Commodore-64 мястото в паметта обикновено е един байт, но понякога може да бъде два последователни байта, когато се вземат предвид указателите (индиректно адресиране). При модерен x86 компютър местоположението в паметта е 16 последователни байта, когато се работи с двойна четворна дума от 16 байта (128 бита), 8 последователни байта, когато се работи с четворна дума от 8 байта (64 бита), 4 последователни байта, когато се работи с двойна дума от 4 байта (32 бита), 2 последователни байта при работа с дума от 2 байта (16 бита) и 1 байт при работа с байт (8 бита). При модерен ARM компютър мястото в паметта е 8 последователни байта, когато се работи с двойна дума от 8 байта (64 бита), 4 последователни байта, когато се работи с дума от 4 байта (32 бита), 2 последователни байта, когато се работи с полудума от 2 байта (16 бита) и 1 байт, когато се работи с байт (8 бита).

Тази глава обяснява какво е общото в архитектурите CISC и RISC и какви са техните разлики. Това се прави в сравнение с 6502 µP и компютъра commodore-64, където е приложимо.

6.2 Блокова схема на дънната платка на съвременния компютър

PC означава персонален компютър. Следното е обща основна блокова схема за съвременна дънна платка с един микропроцесор за персонален компютър. Представлява CISC или RISC дънна платка.


Фиг. 6.21 Основна блокова схема на дънната платка на съвременния компютър

На диаграмата са показани три вътрешни порта, но на практика има повече. Всеки порт има регистър, който може да се разглежда като самия порт. Всяка портова верига има поне още един регистър, който може да се нарече „регистър на състоянието“. Регистърът на състоянието показва порта към програмата, която изпраща сигнала за прекъсване към микропроцесора. Има схема на контролер за прекъсване (не е показана), която прави разлика между различните линии за прекъсване от различните портове и има само няколко линии към µP.

HD.C в диаграмата означава Hard Drive Card. NIC означава мрежова интерфейсна карта. Картата (веригата) на твърдия диск е свързана към твърдия диск, който е вътре в основния модул (системен блок) на съвременния компютър. Мрежовата интерфейсна карта (верига) е свързана чрез външен кабел към друг компютър. На диаграмата има един порт и DMA (вижте следващата илюстрация), които са свързани към картата с твърд диск и/или към мрежовата интерфейсна карта. DMA означава Директен достъп до паметта.

Спомнете си от главата за компютъра Commodore-64, че за да изпратите байтовете от паметта към дисковото устройство или друг компютър, всеки байт трябва да бъде копиран в регистър в микропроцесора, преди да бъде копиран в съответния вътрешен порт, и след това автоматично към устройството. За да получите байтовете от дисковото устройство или друг компютър в паметта, всеки байт трябва да бъде копиран от съответния регистър на вътрешния порт в регистър на микропроцесора, преди да бъде копиран в паметта. Това обикновено отнема много време, ако броят на байтовете в потока е голям. Решението за бърз трансфер е използването на Direct Memory Access (схема) без преминаване през микропроцесора.

DMA веригата е между порта и HD. C или NIC. С директния достъп до паметта на веригата DMA, прехвърлянето на големи потоци от байтове е директно между веригата DMA и паметта (RAM) без непрекъснатото участие на микропроцесора. DMA използва адресната шина и шината за данни вместо µP. Общата продължителност на трансфера е по-кратка, отколкото ако трябва да се използва µP hard. Както HD C., така и NIC използват DMA, когато имат голям поток от данни (байтове) за прехвърляне с RAM (паметта).

GPU означава графичен процесор. Този блок на дънната платка е отговорен за изпращането на текста и движещите се или неподвижни изображения към екрана.

При съвременните компютри (компютри) няма памет само за четене (ROM). Има обаче BIOS или UEFI, който е вид енергонезависима RAM. Информацията в BIOS всъщност се поддържа от батерия. Батерията е това, което всъщност поддържа и таймера на часовника в точното време и дата за компютъра. UEFI е изобретен след BIOS и е заменил BIOS, въпреки че BIOS все още е доста актуален в съвременните компютри. Ще обсъдим повече за тях по-късно!

В съвременните компютри шините за адрес и данни между µP и веригите на вътрешния порт (и паметта) не са паралелни шини. Те са серийни шини, които се нуждаят от два проводника за предаване в една посока и други два проводника за предаване в обратна посока. Това означава, например, че 32 бита могат да бъдат изпратени последователно (един бит след друг) във всяка посока.

Ако серийното предаване е само в една посока с два проводника (две линии), това се нарича полудуплексно. Ако серийното предаване е в двете посоки с четири проводника, по една двойка във всяка посока, това се казва, че е пълен дуплекс.

Цялата памет на съвременния компютър все още се състои от поредица от байтове: осем бита на байт. Съвременният компютър има пространство в паметта от поне 4 гигабайта = 4 x 210 x 2 10 х 2 10 = 4 х 1,073,741,824 10 байтове = 4 x 1024 10/под> x 1024 10 x 1024 10 = 4 х 1,073,741,824 10 .

Забележка : Въпреки че на предишната дънна платка не е показана таймерна схема, всички съвременни дънни платки имат таймерни схеми.

6.3 Основи на x64 компютърната архитектура

6.31 Наборът от регистри x64
64-битовият микропроцесор от серията микропроцесори x86 е 64-битов микропроцесор. Съвсем модерно е да се замени 32-битов процесор от същата серия. Регистрите с общо предназначение на 64-битовия микропроцесор и техните имена са както следва:


Фиг. 6.31 Регистри с общо предназначение за x64

Шестнадесет (16) регистъра с общо предназначение са показани на дадената илюстрация. Всеки от тези регистри е 64-битов. Поглеждайки регистъра в горния ляв ъгъл, 64-те бита са идентифицирани като RAX. Първите 32 бита от същия регистър (отдясно) се идентифицират като EAX. Първите 16 бита от същия регистър (отдясно) се идентифицират като AX. Вторият байт (отдясно) на същия този регистър е идентифициран като AH (H тук означава високо). И първият байт (на същия този регистър) се идентифицира като AL (L тук означава ниско). Поглеждайки регистъра в долния десен ъгъл, 64-те бита са идентифицирани като R15. Първите 32 бита от същия регистър са идентифицирани като R15D. Първите 16 бита от същия регистър са идентифицирани като R15W. И първият байт е идентифициран като R15B. Имената на другите регистри (и подрегистри) са обяснени по подобен начин.

Има някои разлики между Intel и AMD µP. Информацията в този раздел е за Intel.

При 6502 µP регистърът на програмния брояч (недостъпен директно), който съдържа следващата инструкция за изпълнение, е с ширина 16 бита. Тук (x64) програмният брояч се нарича Instruction Pointer и е 64-битов. Той е обозначен като RIP. Това означава, че x64 µP може да адресира до 264 = 1,844674407 x 1019 (всъщност 18,446,744,073,709,551,616) местоположения в байт памет. RIP не е регистър с общо предназначение.

Регистърът на указателя на стека или RSP е сред 16-те регистъра с общо предназначение. Той сочи към последния запис в стека в паметта. Както при 6502 µP, стекът за x64 расте надолу. При x64 стекът в RAM се използва за съхраняване на адресите за връщане за подпрограми. Използва се и за съхраняване на „пространството на сенките“ (вижте следващата дискусия).

6502 µP има 8-битов регистър за състоянието на процесора. Еквивалентът в x64 се нарича регистър RFLAGS. Този регистър съхранява флаговете, които се използват за резултатите от операциите и за управление на процесора (µP). Той е 64-битов широк. По-високите 32 бита са запазени и не се използват в момента. Следната таблица дава имената, индекса и значенията на често използваните битове в регистъра RFLAGS:

Таблица 6.31.1
Най-използваните RFLAGS флагове (битове)
Символ малко Име Предназначение
CF 0 Носете Задава се, ако аритметична операция генерира пренасяне или заемане на най-значимия бит от резултата; изчистени по друг начин. Този флаг показва условие за препълване за целочислена аритметика без знак. Използва се и в аритметика с многократна точност.
PF 2 Паритет Задава се, ако най-малко значимият байт на резултата съдържа четен брой от 1 бита; изчистени по друг начин.
НА 4 Настройте Задава се, ако аритметична операция генерира пренасяне или заемане на бит 3 от резултата; изчистени по друг начин. Този флаг се използва в двоично кодирана десетична (BCD) аритметика.
ZF 6 Нула Задава се, ако резултатът е нула; изчистени по друг начин.
SF 7 Знак Задава се, ако е равен на най-значимия бит от резултата, който е знаковият бит на цяло число със знак (0 показва положителна стойност, а 1 показва отрицателна стойност).
НА единадесет препълване Задава се, ако целочисленият резултат е твърде голямо положително число или твърде малко отрицателно число (с изключение на знаковия бит), за да се побере в целевия операнд; изчистени по друг начин. Този флаг показва условие за препълване за аритметиката на цяло число със знак (допълнение от две).
DF 10 Посока Задава се, ако инструкциите на низа за посока работят (увеличаване или намаляване).
документ за самоличност двадесет и едно Идентификация Задава се, ако неговата променливост обозначава наличието на инструкцията CPUID.

В допълнение към осемнадесетте 64-битови регистъра, които са посочени по-рано, x64 архитектурата µP има осем 80-битови широки регистъра за аритметика с плаваща запетая. Тези осем регистъра могат да се използват и като MMX регистри (вижте следващата дискусия). Има също шестнадесет 128-битови регистъра за XMM (вижте следващата дискусия).

Това не е всичко относно регистрите. Има повече x64 регистри, които са сегментни регистри (най-често неизползвани в x64), контролни регистри, регистри за управление на паметта, регистри за отстраняване на грешки, регистри за виртуализация, регистри за производителност, които проследяват всички видове вътрешни параметри (попадения/пропуски в кеша, изпълнени микрооперации, време , и още много).

SIMD

SIMD означава Single Instruction Multiple Data. Това означава, че една инструкция на асемблерния език може да действа върху множество данни едновременно в един микропроцесор. Разгледайте следната таблица:

1 2 3 4 5 6 7 8
+ 9 10 единадесет 12 13 14 петнадесет 16
= 10 12 14 16 18 двадесет 22 24

В тази таблица осем двойки числа се добавят паралелно (в една и съща продължителност), за да дадат осем отговора. Една инструкция на асемблерния език може да направи осемте паралелни добавяния на цели числа в MMX регистрите. Подобно нещо може да се направи с XMM регистрите. И така, има MMX инструкции за цели числа и XMM инструкции за плаващи числа.

6.32 Карта на паметта и x64

Тъй като указателят на инструкциите (програмният брояч) има 64 бита, това означава, че могат да бъдат адресирани 264 = 1,844674407 x 1019 места в байта на паметта. В шестнадесетичен най-високият байт е FFFF,FFFF,FFFF,FFFF16. Никой обикновен компютър днес не може да осигури толкова голямо (пълно) пространство в паметта. И така, подходяща карта на паметта за x64 компютър е както следва:

Забележете, че празнината от 0000,8000,0000,000016 до FFFF,7FFF,FFFF,FFFF16 няма местоположения в паметта (няма банки RAM памет). Това е разлика от FFFF,0000,0000,000116, която е доста голяма. Каноничната висока половина съдържа операционната система, докато каноничната ниска половина съдържа потребителските програми (приложения) и данни. Операционната система се състои от две части: малък UEFI (BIOS) и голяма част, които се зареждат от твърдия диск. Следващата глава говори повече за съвременните операционни системи. Обърнете внимание на приликата с тази карта на паметта и тази за Commodore-64, когато 64KB може да изглеждат като много памет.

В този контекст операционната система се нарича грубо „ядро“. Ядрото е подобно на ядрото на компютъра Commodore-64, но има много повече подпрограми.

Endianness за x64 е little endian, което означава, че за местоположение долният адрес сочи към по-ниския байт съдържание в паметта.

6.33 Режими на адресиране на асемблер за x64

Режимите на адресиране са начините, по които една инструкция може да има достъп до µP регистрите и паметта (включително регистрите на вътрешния порт). x64 има много режими на адресиране, но тук се разглеждат само често използваните режими на адресиране. Общият синтаксис за инструкция тук е:

дестинация на операционния код, източник

Десетичните числа се записват без префикс или наставка. При 6502 източникът е имплицитен. x64 има повече операционни кодове от 6502, но някои от операционните кодове имат същата мнемоника. Индивидуалните x64 инструкции са с променлива дължина и могат да варират по размер от 1 до 15 байта. Често използваните режими на адресиране са както следва:

Режим на незабавно адресиране
Тук операндът източник е действителна стойност, а не адрес или етикет. Пример (прочетете коментара):

ДОБАВЯНЕ на EAX, 14; добавете десетичен знак 14 към 32-битов EAX на 64-битов RAX, отговорът остава в EAX (дестинация)

Регистрирайте се, за да регистрирате режим на адресиране
Пример:

ДОБАВИ R8B, AL ; добавете 8-битов AL на RAX към R8B на 64-битов R8 – отговорите остават в R8B (дестинация)

Режим на индиректно и индексирано адресиране
Непрякото адресиране с 6502 µP означава, че местоположението на дадения адрес в инструкцията има ефективния адрес (указател) на крайното местоположение. Подобно нещо се случва с x64. Индексното адресиране с 6502 µP означава, че съдържанието на µP регистър се добавя към дадения адрес в инструкцията, за да има ефективния адрес. Подобно нещо се случва с x64. Също така, с x64, съдържанието на регистъра може също да бъде умножено по 1 или 2 или 4 или 8, преди да бъде добавено към дадения адрес. Инструкцията mov (копиране) на x64 може да комбинира както индиректно, така и индексирано адресиране. Пример:

MOV R8W, 1234[8*RAX+RCX]; преместване на дума на адрес (8 x RAX + RCX) + 1234

Тук R8W има първите 16 бита на R8. Даденият адрес е 1234. Регистърът RAX има 64-битово число, което се умножава по 8. Резултатът се добавя към съдържанието на 64-битовия регистър RCX. Този втори резултат се добавя към дадения адрес, който е 1234, за да се получи ефективният адрес. Числото в местоположението на ефективния адрес се премества (копира) на първото 16-битово място (R8W) на регистъра R8, замествайки всичко, което е било там. Обърнете внимание на използването на квадратните скоби. Не забравяйте, че една дума в x64 е широка 16 бита.

Относително адресиране на RIP
За 6502 µP относителното адресиране се използва само с инструкции за разклоняване. Там единственият операнд на кода на операцията е отместване, което се добавя или изважда към съдържанието на програмния брояч за адреса на ефективната инструкция (не адреса на данните). Подобно нещо се случва с x64, където програмният брояч се нарича като указател на инструкции. Инструкцията с x64 не трябва да бъде само инструкция за разклоняване. Пример за RIP-относително адресиране е:

MOV AL, [RIP]

AL на RAX има 8-битово число със знак, което се добавя или изважда от съдържанието в RIP (64-битов указател на инструкция), за да посочи следващата инструкция. Имайте предвид, че източникът и дестинацията са разменени по изключение в тази инструкция. Също така обърнете внимание на използването на квадратните скоби, които се отнасят до съдържанието на RIP.

6.34 Често използвани инструкции на x64

В следващата таблица * означава различни възможни суфикси на подмножество от кодове за операции:

Таблица 6.34.1
Често използвани инструкции в x64
Операционен код Значение
MOV Преместване (копиране) към/от/между паметта и регистрите
CMOV* Различни условни ходове
XCHG Размяна
BSWAP Размяна на байтове
PUSH/POP Използване на стека
ADD/ADC Добавяне/с пренасяне
SUB/SBC Изваждане/с пренасяне
МУЛ/ИМУЛ Умножение/без знак
DIV/IDIV Разделяне/без знак
INC/DEC Увеличаване/намаляване
ОТРИЦ Отхвърляне
CMP Сравнете
И/ИЛИ/XOR/НЕ Побитови операции
SHR/SAR Shift надясно логически/аритметичен
SHL/SAL Преместване наляво логическо/аритметично
ROR/РОЛЯ Завъртете надясно/наляво
RCR/RCL Завъртете надясно/наляво през накрайника за носене
BT/BTS/BTR Тест на битове/и настройка/и нулиране
JMP Безусловен скок
JE/JNE/JC/JNC/J* Скачайте, ако е равно/не е равно/ носи/не носи/много други
РАЗХОДЯ/ХОДЯ/ХОДЯ Цикъл с ECX
ОБАЖДАНЕ/РЕТ Извикване на подпрограма/връщане
NOP Без операция
CPUID Информация за процесора

x64 има инструкции за умножение и деление. Той има хардуерни схеми за умножение и деление в своя µP. 6502 µP няма хардуерни схеми за умножение и деление. По-бързо е да се направи умножението и делението чрез хардуер, отколкото чрез софтуер (включително преместването на битове).

Инструкции за низове
Има редица инструкции за низове, но единствената, която трябва да се обсъди тук, е инструкцията MOVS (за преместване на низ) за копиране на низ, започващ от адрес C000 з . За да започнете от адрес C100 з , използвайте следната инструкция:

MOVS [C100H], [C000H]

Обърнете внимание на суфикса H за шестнадесетичен.

6.35 Зацикляне в x64

6502 µP има инструкции за разклоняване за цикъл. Инструкция за разклоняване прескача до адресно местоположение, което има новата инструкция. Местоположението на адреса може да се нарече „примка“. x64 има инструкции LOOP/LOOPE/LOOPNE за зацикляне. Тези запазени думи на асемблерния език не трябва да се бъркат с етикета „цикъл“ (без кавичките). Поведението е следното:

LOOP намалява ECX и проверява дали ECX не е нула. Ако това условие (нула) е изпълнено, той преминава към определен етикет. В противен случай се проваля (продължете с останалите инструкции в следващата дискусия).

LOOPE намалява ECX и проверява дали ECX не е нула (може да е 1 например) и ZF е зададено (на 1). Ако тези условия са изпълнени, той скача на етикета. В противен случай пропада.

LOOPNE намалява ECX и проверява дали ECX не е нула и ZF НЕ Е зададено (т.е. е нула). Ако тези условия са изпълнени, той преминава към етикета. В противен случай пропада.

При x64 регистърът RCX или неговите подчасти като ECX или CX съдържат цялото число на брояча. С инструкциите LOOP броячът обикновено отброява, като намалява с 1 за всеки скок (цикъл). В следващия цикличен кодов сегмент числото в EAX регистъра се увеличава от 0 до 10 за десет итерации, докато числото в ECX се брои (намалява) 10 пъти надолу (прочетете коментарите):

MOV EAX, 0;
MOV ECX, 10; обратно броене 10 пъти по подразбиране, веднъж за всяка итерация
етикет:
INC EAX ; увеличава EAX като тяло на цикъл
етикет LOOP; намалява EAX и ако EAX не е нула, изпълнете повторно тялото на цикъла от „етикет:“

Кодирането на цикъла започва от „етикет:“. Обърнете внимание на използването на дебелото черво. Кодирането на цикъла завършва с „етикета LOOP“, който казва decrement EAX. Ако съдържанието му не е нула, върнете се към инструкцията след „етикет:“ и изпълнете отново всяка инструкция (всички инструкции от тялото), която идва надолу до „етикет LOOP“. Имайте предвид, че „етикет“ може да има друго име.

6.36 Вход/Изход на x64

Този раздел на главата се занимава с изпращане на данни към изходен (вътрешен) порт или получаване на данните от входен (вътрешен) порт. Чипсетът има осем битови портове. Всеки два последователни 8-битови порта могат да се третират като 16-битов порт, а всеки четири последователни порта могат да бъдат 32-битов порт. По този начин процесорът може да прехвърля 8, 16 или 32 бита към или от външно устройство.

Информацията може да се прехвърля между процесора и вътрешния порт по два начина: като се използва това, което е известно като картографиран вход/изход или използвайки отделно адресно пространство за вход/изход. I/O, картографиран в паметта, е като това, което се случва с процесора 6502, където адресите на портовете всъщност са част от цялото пространство на паметта. В този случай, когато изпращате данните до определен адрес, те отиват към порт, а не към банка с памет. Портовете може да имат отделно I/O адресно пространство. В този последен случай всички банки памет имат своите адреси от нула. Има отделен адресен диапазон от 0000H до FFFF16. Те се използват от портовете в чипсета. Дънната платка е програмирана, за да не се бърка между I/O картографиран в паметта и отделно I/O адресно пространство.

I/O с карта на паметта
С това портовете се считат за местоположения в паметта и нормалните операционни кодове за използване между паметта и µP се използват за пренос на данни между µP и портове. И така, за да преместите байт от порт на адрес F000H към µP регистъра RAX:EAX:AX:AL, направете следното:

MOV AL, [F000H]

Низ може да бъде преместен от паметта към порт и обратно. Пример:

MOVS [F000H], [C000H]; източникът е C000H, а местоназначението е порт на F000H.

Отделно I/O адресно пространство

При това трябва да се използват специалните инструкции за вход и изход.

Прехвърляне на единични елементи
Процесорният регистър за трансфера е RAX. Всъщност това е RAX:EAX за двойна дума, RAX:EAX:AX ​​за дума и RAX:EAX:AX:AL за байт. И така, за да прехвърлите байт от порт на FFF0h към RAX:EAX:AX:AL, въведете следното:

В AL, [FFF0H]

За обратен трансфер въведете следното:

ИЗХОД [FFF0H], AL

Така че, за единични елементи, инструкциите са IN и OUT. Адресът на порта може също да бъде даден в регистъра RDX:EDX:DX.

Прехвърляне на низове
Низ може да бъде прехвърлен от паметта към порт на чипсет и обратно. За да прехвърлите низ от порт на адрес FFF0H към паметта, започнете от C100H, въведете:

INS [ESI], [DX]

което има същия ефект като:

INS [EDI], [DX]

Програмистът трябва да постави двубайтовия адрес на порта на FFF0H в регистъра RDX:EDX:Dx и трябва да постави двубайтовия адрес на C100H в регистъра RSI:ESI или RDI:EDI. За обратен трансфер направете следното:

INS [DX], [ESI]

което има същия ефект като:

INS [DX], [EDI]

6.37 Стекът в x64

Подобно на процесора 6502, процесорът x64 също има стек в RAM. Стекът за x64 може да бъде 2 16 = дължина 65 536 байта или може да бъде 2 32 = дължина 4 294 967 296 байта. Расте и надолу. Когато съдържанието на регистър се избута в стека, числото в RSP указателя на стека се намалява с 8. Не забравяйте, че адресът на паметта за x64 е широк 64 бита. Стойността в указателя на стека в µP сочи към следващото местоположение в стека в RAM. Когато съдържанието на регистър (или стойност в един операнд) се извади от стека в регистър, числото в RSP указателя на стека се увеличава с 8. Операционната система решава размера на стека и къде започва в RAM и расте надолу. Не забравяйте, че стекът е структура „Последен влязъл, първи излязъл“ (LIFO), която расте надолу и се свива нагоре в този случай.

За да изпратите съдържанието на µP RBX регистъра към стека, направете следното:

НАТИСНЕТЕ RBX

За да върнете последния запис в стека обратно в RBX, направете следното:

POP RBX

6.38 Процедура в x64

Подпрограмата в x64 се нарича „процедура“. Стекът се използва тук повече, отколкото се използва за 6502 µP. Синтаксисът за x64 процедура е:

proc_name:
процедурно тяло

точно

Преди да продължите, забележете, че операционните кодове и етикетите за x64 подпрограма (инструкции за език за асемблиране като цяло) не са чувствителни към главни и малки букви. Това е proc_name е същото като PROC_NAME. Подобно на 6502, името на името на процедурата (етикет) започва в началото на нов ред в текстовия редактор за асемблерния език. Това е последвано от двоеточие, а не от интервал и код на операцията, както при 6502. Следва тялото на подпрограмата, завършващо с RET, а не с RTS, както при 6502 µP. Както при 6502, всяка инструкция в тялото, включително RET, не започва в началото на своя ред. Имайте предвид, че един етикет тук може да бъде с дължина повече от 8 знака. За да извикате тази процедура отгоре или под въведената процедура, направете следното:

CALL proc_name

При 6502 името на етикета е само тип за повикване. Тук обаче се въвежда запазената дума „CALL“ или „call“, последвана от името на процедурата (подпрограма) след интервал.

Когато се работи с процедури, обикновено има две процедури. Едната процедура извиква другата. Процедурата, която извиква (има инструкцията за повикване), се нарича „извикващ“, а процедурата, която се извиква, се нарича „извикващ“. Има конвенция (правила), която трябва да се следва.

Правила на обаждащия се

Повикващият трябва да се придържа към следните правила, когато извиква подпрограма:

1. Преди да извика подпрограма, извикващият трябва да запише съдържанието на определени регистри, които са обозначени като записани в стека. Запазените от повикващия регистри са R10, R11 и всички регистри, в които са поставени параметрите (RDI, RSI, RDX, RCX, R8, R9). Ако съдържанието на тези регистри трябва да се запази в извикването на подпрограмата, избутайте ги в стека, вместо да ги записвате в RAM. Това трябва да се направи, защото регистрите трябва да се използват от извиквания за изтриване на предишното съдържание.

2. Ако процедурата е да се добавят две числа например, двете числа са параметрите, които трябва да бъдат предадени на стека. За да предадете параметрите на подпрограмата, поставете шест от тях в следните регистри в ред: RDI, RSI, RDX, RCX, R8, R9. Ако има повече от шест параметъра към подпрограмата, избутайте останалите в стека в обратен ред (т.е. последният параметър първи). Тъй като стекът расте надолу, първият от допълнителните параметри (всъщност седмият параметър) се съхранява на най-ниския адрес (тази инверсия на параметри е използвана исторически, за да позволи на функциите (подпрограмите) да бъдат предавани с променлив брой параметри).

3. За да извикате подпрограмата (процедурата), използвайте инструкцията за извикване. Тази инструкция поставя адреса за връщане отгоре на параметрите в стека (най-ниската позиция) и разклоненията към кода на подпрограмата.

4. След като подпрограмата се върне (т.е. непосредствено след инструкцията за извикване), повикващият трябва да премахне всички допълнителни параметри (освен шестте, които се съхраняват в регистрите) от стека. Това възстановява стека до състоянието му преди извикването да бъде извършено.

5. Повикващият може да очаква да намери върнатата стойност (адрес) на подпрограмата в RAX регистъра.

6. Повикващият възстановява съдържанието на записаните от повикващия регистри (R10, R11 и всички в регистрите за предаване на параметри), като ги изважда от стека. Обаждащият се може да приеме, че няма други регистри, променени от подпрограмата.

Поради начина, по който е структурирана конвенцията за извикване, обикновено е така, че някои (или повечето) от тези стъпки няма да направят никакви промени в стека. Например, ако има шест или по-малко параметъра, нищо не се избутва в стека в тази стъпка. По същия начин програмистите (и компилаторите) обикновено пазят резултатите, които ги интересуват, извън записаните от повикващия регистри в стъпки 1 и 6, за да предотвратят излишните натискания и изскачания.

Има два други начина за предаване на параметрите на подпрограма, но те няма да бъдат разгледани в този онлайн курс за кариера. Един от тях използва самия стек вместо регистрите с общо предназначение.

Правилата на Callee

Дефиницията на извиканата подпрограма трябва да се придържа към следните правила:

1. Разпределете локалните променливи (променливи, които са разработени в рамките на процедурата), като използвате регистрите или като освободите място в стека. Припомнете си, че стекът расте надолу. Така че, за да освободите място в горната част на стека, указателят на стека трябва да бъде намален. Стойността, с която указателят на стека се намалява, зависи от необходимия брой локални променливи. Например, ако са необходими локален float и local long (общо 12 байта), указателят на стека трябва да бъде намален с 12, за да се освободи място за тези локални променливи. В език от високо ниво като C, това означава да декларирате променливите без да присвоявате (инициализирате) стойностите.

2. След това трябва да се запишат стойностите на всички регистри, които са обозначени като запазени за извиквания (регистри с общо предназначение, които не са записани от повикващия), които се използват от функцията. За да запазите регистрите, бутнете ги в стека. Регистрите, записани от извиквания, са RBX, RBP и R12 до R15 (RSP също се запазва от конвенцията за повикване, но не е необходимо да се изпраща в стека по време на тази стъпка).

След като тези три действия бъдат извършени, действителната работа на подпрограмата може да продължи. Когато подпрограмата е готова да се върне, правилата за конвенция за повикване продължават.

3. Когато подпрограмата е готова, върнатата стойност за подпрограмата трябва да бъде поставена в RAX, ако вече не е там.

4. Подпрограмата трябва да възстанови старите стойности на всички запазени от извиквания регистри (RBX, RBP и R12 до R15), които са били модифицирани. Съдържанието на регистъра се възстановява чрез изваждането му от стека. Обърнете внимание, че регистрите трябва да бъдат извадени в обратния ред, в който са били натиснати.

5. След това освобождаваме локалните променливи. Най-лесният начин да направите това е да добавите към RSP същата сума, която е била извадена от нея в стъпка 1.

6. Накрая се връщаме към повикващия чрез изпълнение на инструкция ret. Тази инструкция ще намери и премахне подходящия адрес за връщане от стека.

Пример за тялото на извикваща подпрограма за извикване на друга подпрограма, която е „myFunc“, е както следва (прочетете коментарите):

; Искате да извикате функция „myFunc“, която отнема три
; целочислен параметър. Първият параметър е в RAX.
; Втори параметър е константата 456. Трети
; параметърът е в местоположението на паметта ”variabl”

натиснете rdi; rdi ще бъде параметър, така че го запазваме
; long retVal = myFunc (x, 456, z);

mov rdi, rax; поставете първи параметър в RDI
mov rsi, 456; поставете втори параметър в RSI
mov rdx, [променлива]; поставете трети параметър в RDX

обадете се на myFunc; извикайте функцията

поп rdi ; възстановяване на запазена RDI стойност
; върнатата стойност на myFunc вече е достъпна в RAX

Пример за функция callee (myFunc) е (прочетете коментарите):

myFunc:
; ∗∗∗ Пролог на стандартната подпрограма ∗∗∗
под rsp, 8; място за 64-битова локална променлива (резултат), използвайки „под“ кода на операцията

натиснете rbx; запазване на callee-запазване на регистри
натиснете rbp; и двете ще бъдат използвани от myFunc

; ∗∗∗ Подрутина Тяло ∗∗∗
mov rax, rdi; параметър 1 към RAX
mov rbp, rsi; параметър 2 към RBP
mov rbx, rdx; параметър 3 към rb x
mov [rsp + 1 6], rbx; поставете rbx в локална променлива
добави [rsp + 1 6], rbp; добавете rbp в локална променлива
mov rax, [rsp +16]; mov съдържание на локална променлива в RAX
; (върната стойност/краен резултат)

; ∗∗∗ Епилог на стандартната подпрограма ∗∗∗
поп rbp; възстановяване на регистрите за запис на извиквания
поп rbx; обратно на при натискане
добавете rsp, 8; освободи локална(и) променлива(и). 8 означава 8 байта
ret ; извадете горната стойност от стека, скочете там

6.39 Прекъсвания и изключения за x64

Процесорът предоставя два механизма за прекъсване на изпълнението на програмата, прекъсвания и изключения:

  • Прекъсването е асинхронно (може да се случи по всяко време) събитие, което обикновено се задейства от I/O устройство.
  • Изключение е синхронно събитие (случва се, когато кодът се изпълнява, предварително програмиран, въз основа на някакво събитие), което се генерира, когато процесорът открие едно или повече предварително дефинирани условия, докато изпълнява инструкция. Посочени са три класа изключения: грешки, прихващания и прекъсвания.

Процесорът реагира на прекъсвания и изключения по същество по същия начин. Когато се сигнализира за прекъсване или изключение, процесорът спира изпълнението на текущата програма или задача и превключва към манипулираща процедура, която е написана специално за обработка на условието за прекъсване или изключение. Процесорът осъществява достъп до манипулаторната процедура чрез запис в таблицата с дескриптори на прекъсвания (IDT). Когато манипулаторът завърши обработката на прекъсването или изключението, управлението на програмата се връща към прекъснатата програма или задача.

Операционната система, изпълнителната система и/или драйверите на устройства обикновено обработват прекъсванията и изключенията независимо от приложните програми или задачи. Приложните програми обаче могат да имат достъп до манипулаторите на прекъсвания и изключения, които са включени в операционната система или да я изпълняват чрез извикванията на асемблерния език.

Дефинирани са осемнадесет (18) предварително дефинирани прекъсвания и изключения, които са свързани с записи в IDT. Двеста двадесет и четири (224) дефинирани от потребителя прекъсвания също могат да бъдат направени и свързани с таблицата. Всяко прекъсване и изключение в IDT се идентифицира с число, което се нарича „вектор“. Таблица 6.39.1 изброява прекъсванията и изключенията с записи в IDT и съответните им вектори. Вектори от 0 до 8, от 10 до 14 и от 16 до 19 са предварително дефинираните прекъсвания и изключения. Векторите от 32 до 255 са за софтуерно дефинирани прекъсвания (потребител), които са или за софтуерни прекъсвания, или за маскирани хардуерни прекъсвания.

Когато процесорът открие прекъсване или изключение, той прави едно от следните неща:

  • Изпълнете неявно извикване на манипулираща процедура
  • Изпълнете неявно извикване на задача на манипулатор

6.4 Основи на 64-битовата компютърна архитектура на ARM

Архитектурите ARM дефинират семейство RISC процесори, които са подходящи за използване в голямо разнообразие от приложения. ARM е архитектура за зареждане/съхраняване, която изисква данните да бъдат заредени от паметта в регистър, преди каквато и да е обработка, като например операция ALU (аритметична логическа единица), да може да се извърши с тях. Следваща инструкция съхранява резултата обратно в паметта. Въпреки че това може да изглежда като стъпка назад от архитектурите x86 и x64, които работят директно върху операндите в паметта в една инструкция (използвайки регистрите на процесора, разбира се), подходът зареждане/съхраняване на практика позволява няколко последователни операции да се изпълнява с висока скорост върху операнд, след като той бъде зареден в един от многото процесорни регистри. ARM процесорите имат опцията за малък или голям ред. Настройката по подразбиране ARM 64 е little-endian, което е конфигурацията, която обикновено се използва от операционните системи. 64-битовата ARM архитектура е модерна и е настроена да замени 32-битовата ARM архитектура.

Забележка : Всяка инструкция за 64-битовия ARM µP е с дължина 4 байта (32 бита).

6.41 64-битовият набор от ARM регистри
Има 31 64-битови регистъра с общо предназначение за 64-битовия ARM µP. Следващата диаграма показва регистрите с общо предназначение и някои важни регистри:


Фиг.4.11.1 64-битови регистри с общо предназначение и някои важни регистри

Регистрите с общо предназначение се означават като X0 до X30. Първата 32-битова част за всеки регистър се нарича от W0 до W30. Когато не се подчертава разликата между 32 бита и 64 бита, се използва префиксът „R“. Например R14 се отнася до W14 или X14.

6502 µP има 16-битов програмен брояч и може да адресира 2 16 местоположения на байтове в паметта. 64-битовият ARM µP има 64-битов програмен брояч и може да адресира до 2 64 = 1,844674407 x 1019 (всъщност 18,446,744,073,709,551,616) местоположения в байт памет. Програмният брояч съдържа адреса на следващата инструкция, която трябва да бъде изпълнена. Дължината на инструкцията на ARM64 или AArch64 обикновено е четири байта. Процесорът автоматично увеличава този регистър с четири, след като всяка инструкция бъде извлечена от паметта.

Регистърът на указателя на стека или SP не е сред 31 регистъра с общо предназначение. Указателят на стека на всяка архитектура сочи към последния запис в стека в паметта. За ARM-64 стекът расте надолу.

6502 µP има 8-битов регистър за състоянието на процесора. Еквивалентът в ARM64 се нарича PSTATE регистър. Този регистър съхранява флаговете, които се използват за резултатите от операциите и за управление на процесора (µP). Той е широк 32 бита. Следващата таблица дава имената, индекса и значенията за често използваните битове в регистъра PSTATE:

Таблица 6.41.1
Най-използвани PSTATE флагове (битове)
Символ малко Предназначение
М 0-3 Режим: Текущото ниво на привилегия за изпълнение (USR, SVC и т.н.).
T 4 Thumb: Задава се, ако наборът от инструкции T32 (Thumb) е активен. Ако е ясно, наборът от инструкции на ARM е активен. Потребителският код може да зададе и изчисти този бит.
И 9 Endianness: Задаването на този бит активира режима big-endian. Ако е ясно, режимът на малкия край е активен. По подразбиране е режимът little-endian.
Q 27 Кумулативен флаг за насищане: Задава се, ако в някакъв момент от поредица от операции възникне препълване или насищане
IN 28 Флаг за препълване: Задава се, ако операцията е довела до подписано препълване.
° С 29 Флаг за пренасяне: Показва дали добавянето е довело до пренасяне или изваждането е довело до заемане.
СЪС 30 Нулев флаг: Задава се, ако резултатът от операция е нула.
н 31 Отрицателен флаг: Задава се, ако резултатът от дадена операция е отрицателен.

ARM-64 µP има много други регистри.

SIMD
SIMD означава Единична инструкция, множество данни. Това означава, че една инструкция на асемблерния език може да действа върху множество данни едновременно в един микропроцесор. Има тридесет и два регистъра с ширина 128 бита за използване със SIMD и операции с плаваща запетая.

6.42 Картографиране на паметта
RAM и DRAM са памети с произволен достъп. DRAM работи по-бавно от RAM. DRAM е по-евтин от RAM. Ако в паметта има повече от 32 гигабайта (GB) непрекъсната DRAM, ще има повече проблеми с управлението на паметта: 32 GB = 32 x 1024 x 1024 x 1024 байта. За цялото пространство на паметта, което е далеч по-голямо от 32 GB, DRAM над 32 GB трябва да бъде осеяно с RAM за по-добро управление на паметта. За да разберете картата на паметта ARM-64, първо трябва да разберете картата на паметта от 4 GB за 32-битовия централен процесор (CPU) на ARM. CPU означава µP. За 32-битов компютър максималното адресируемо пространство в паметта е 2 32 = 4 х 2 10 х 2 10 х 2 10 = 4 x 1024 x 1024 x 1024 = 4 294 967 296 = 4 GB.

32-битова ARM карта на паметта
Картата на паметта за 32-битов ARM е:

За 32-битов компютър максималният размер на цялата памет е 4 GB. От адреса 0GB до адреса 1GB са ROM операционната система, RAM и I/O местоположенията. Цялата идея за ROM OS, RAM и I/O адреси е подобна на ситуацията на Commodore-64 с възможен 6502 CPU. OS ROM за Commodore-64 е в горния край на паметта. ROM OS тук е много по-голяма от тази на Commodore-64 и е в началото на цялото адресно пространство на паметта. В сравнение с други съвременни компютри, ROM OS тук е пълна, в смисъл, че е сравнима с количеството OS в техните твърди дискове. Има две основни причини за наличието на ОС в ROM интегралните схеми: 1) ARM процесорите се използват предимно в малки устройства като смартфони. Много твърди дискове са по-големи от смартфони и други малки устройства, 2) за сигурност. Когато ОС е в паметта само за четене, тя не може да бъде повредена (презаписани части) от хакери. RAM секциите и входно/изходните секции също са много големи в сравнение с тези на Commodore-64.

Когато се включи захранването с 32-битовата ROM операционна система, операционната система трябва да стартира (зарежда от) адрес 0x00000000 или адрес 0xFFFF0000, ако HiVECs е активиран. Така че, когато захранването се включи след фазата на нулиране, хардуерът на процесора зарежда 0x00000000 или 0xFFFF0000 на програмния брояч. Префиксът '0x' означава шестнадесетичен. Адресът за стартиране на ARMv8 64-битовите процесори е дефинирана реализация. Въпреки това, авторът съветва компютърния инженер да започне от 0x00000000 или 0xFFFF0000 в името на обратната съвместимост.

От 1GB до 2GB е картографираният вход/изход. Има разлика между картографираните I/O и само I/O, които се намират между 0GB и 1GB. При I/O адресът за всеки порт е фиксиран, както при Commodore-64. При картографирани I/O адресът за всеки порт не е непременно един и същ за всяка операция на компютъра (динамичен).

От 2GB до 4GB е DRAM. Това е очакваната (или обичайна) RAM. DRAM означава Dynamic RAM, не е смисълът на променящ се адрес по време на компютърна работа, а в смисъл, че стойността на всяка клетка във физическата RAM трябва да се опреснява при всеки тактов импулс.

Забележка :

  • От 0x0000,0000 до 0x0000, FFFF е OS ROM.
  • От 0x0001,0000 до 0x3FFF,FFFF може да има повече ROM, след това RAM и след това някои I/O.
  • От 0x4000,0000 до 0x7FFF,FFFF е разрешен допълнителен I/O и/или картографиран I/O.
  • От 0x8000,0000 до 0xFFFF, FFFF е очакваната DRAM памет.

Това означава, че на практика очакваната DRAM не трябва да започва от границата от 2 GB памет. Защо програмистът трябва да спазва идеалните граници, когато няма достатъчно физически RAM банки, които са поставени на дънната платка? Това е така, защото клиентът няма достатъчно пари за всички RAM банки.

36-битова ARM карта на паметта
За 64-битов ARM компютър всичките 32 бита се използват за адресиране на цялата памет. За 64-битов ARM компютър, първите 36 бита могат да се използват за адресиране на цялата памет, която в този случай е 2 36 = 68 719 476 736 = 64 GB. Това вече е много памет. Обикновените компютри днес не се нуждаят от това количество памет. Това все още не е достигнало максималния обхват на паметта, която може да бъде достъпна от 64 бита. Картата на паметта за 36-бита за ARM CPU е:

От 0GB адрес до 4GB адрес е 32-битовата карта на паметта. „Запазено“ означава, че не се използва и се съхранява за бъдеща употреба. Не е необходимо банките с физическа памет да са поставени на дънната платка за това пространство. Тук DRAM и картографираният I/O имат същите значения като за 32-битовата карта на паметта.

На практика може да се срещне следната ситуация:

  • 0x1 0000 0000 – 0x3 FFFF FFFF; запазено. 12GB адресно пространство е запазено за бъдеща употреба.
  • 0x4 0000 0000 – 0x7 FFFF FFFF; картографиран I/O. 16 GB адресно пространство е налично за динамично картографирани I/O.
  • 0x8 0000 0000 – 0x8 7FFF FFFF FFFF; Дупка или DRAM. 2 GB адресно пространство може да съдържа едно от следните:
    • Дупка за активиране на разделяне на DRAM устройство (както е описано в следващата дискусия).
    • DRAM.
  • 0x8 8000 0000 – 0xF FFFF FFFF; DRAM. 30GB адресно пространство за DRAM.

Тази карта на паметта е надмножество на 32-битовата адресна карта, като допълнителното пространство е разделено като 50% DRAM (1/2) с опционална дупка в него и 25% картографирано I/O пространство и запазено пространство (1/4 ). Останалите 25% (1/4) са за 32-битовата карта на паметта ½ + ¼ + ¼ = 1.

Забележка : От 32 бита до 360 бита е добавяне на 4 бита към най-значимата страна на 36 бита.

40-битова карта на паметта
40-битовата адресна карта е надмножество на 36-битовата адресна карта и следва същия модел от 50% DRAM с опционална дупка в нея, 25% картографирано I/O пространство и запазено пространство и останалите 25% място за предишната карта на паметта (36-битова). Диаграмата за картата на паметта е:

Размерът на отвора е 544 – 512 = 32GB. На практика може да се срещне следната ситуация:

  • 0x10 0000 0000 – 0x3F FFFF FFFF; запазено. 192GB адресно пространство е запазено за бъдеща употреба.
  • 0x40 0000 0000 – 0x7F FFFF FFFF; картографиран. I/O 256GB адресно пространство е налично за динамично картографиран I/O.
  • 0x80 0000 0000 – 0x87 FFFF FFFF; дупка или DRAM. 32 GB адресно пространство може да съдържа едно от следните:
    • Дупка за активиране на разделяне на DRAM устройство (както е описано в следващата дискусия)
    • DRAM
  • 0x88 0000 0000 – 0xFF FFFF FFFF; DRAM. 480 GB адресно пространство за DRAM.

Забележка : От 36 бита до 40 бита е добавяне на 4 бита към най-значимата страна на 36 бита.

Дупка за DRAM
В картата на паметта отвъд 32-бита това е или DRAM Hole, или продължение на DRAM отгоре. Когато е дупка, трябва да се оцени по следния начин: DRAM дупката осигурява начин за разделяне на голямо DRAM устройство на множество адресни диапазони. Опционалната дупка за DRAM се предлага в началото на по-високата граница на адреса на DRAM. Това позволява опростена схема за декодиране при разделяне на DRAM устройство с голям капацитет в по-ниския физически адресиран регион.

Например, част от 64GB DRAM е подразделена на три региона с отмествания на адреса, извършени чрез просто изваждане в битовете на адреса от висок ред, както следва:

Таблица 6.42.1
Пример за 64GB DRAM разделяне с дупки
Физически адреси в SoC Изместване Вътрешен DRAM адрес
2 GBytes (32-битова карта) 0x00 8000 0000 – 0x00 FFFF FFFF -0x00 8000 0000 0x00 0000 0000 – 0x00 7FFF FFFF
30 GBytes (36-битова карта) 0x08 8000 0000 – 0x0F FFFF FFFF -0x08 0000 0000 0x00 8000 0000 – 0x07 FFFF FFFF
32 GBytes (40-битова карта) 0x88 0000 0000 – 0x8F FFFF FFFF -0x80 0000 0000 0x08 0000 0000 – 0x0F FFFF FFFF

Предложени 44-битови и 48-битови карти с адресирана памет за процесори ARM
Да приемем, че един персонален компютър има 1024GB (= 1TB) памет; това е твърде много памет. И така, 44-битовите и 48-битовите адресирани карти на паметта за ARM CPU за 16 TB и съответно 256 TB са само предложения за бъдещи компютърни нужди. Всъщност тези предложения за ARM CPU следват същото разделение на паметта по съотношение като предишните карти на паметта. Това е: 50% DRAM с опционална дупка в нея, 25% картографирано I/O пространство и запазено пространство, а останалите 25% пространство за предишната карта на паметта.

52-битовите, 56-битовите, 60-битовите и 64-битовите адресирани карти на паметта все още предстои да бъдат предложени за ARM 64 бита за далечното бъдеще. Ако учените по това време все още намират разделянето 50 : 25 : 25 на цялото пространство на паметта за полезно, те ще запазят съотношението.

Забележка : SoC означава System-on-Chip, което се отнася до схеми в µP чипа, които иначе не биха били там.

SRAM или статичната памет с произволен достъп е по-бърза от по-традиционната DRAM, но изисква повече силициева площ. SRAM не изисква опресняване. Читателят може да си представи RAM като SRAM.

6.43 Режими на адресиране на асемблерен език за ARM 64
ARM е архитектура за зареждане/съхранение, която изисква данните да бъдат заредени от паметта в регистър на процесора, преди да може да се извърши каквато и да е обработка, като например аритметична логическа операция, с тях. Следваща инструкция съхранява резултата обратно в паметта. Въпреки че това може да изглежда като крачка назад от x86 и последващите x64 архитектури, които работят директно върху операндите в паметта в една инструкция, на практика подходът зареждане/съхраняване позволява няколко последователни операции да се изпълняват с висока скорост на операнд, след като бъде зареден в един от многото процесорни регистри.

Форматът на асемблерния език ARM има прилики и разлики със серията x64 (x86).

  • Изместване : Константа със знак може да бъде добавена към основния регистър. Отместването се въвежда като част от инструкцията. Например: ldr x0, [rx, #10] зарежда r0 с думата на адреса r1+10.
  • Регистрирам : Увеличение без знак, което се съхранява в регистър, може да бъде добавено или извадено от стойността в основен регистър. Например: ldr r0, [x1, x2] зарежда r0 с думата на адреса x1+x2. Всеки от регистрите може да се разглежда като основен регистър.
  • Мащабиран регистър : Увеличението в регистър се измества наляво или надясно с определен брой битови позиции, преди да бъде добавено или извадено от стойността на основния регистър. Например: ldr x0, [x1, x2, lsl #3] зарежда r0 с думата на r1+(r2×8) адреса. Преместването може да бъде логическо изместване наляво или надясно (lsl или lsr), което вмъква нулеви битове в освободените битови позиции или аритметично изместване надясно (asr), което репликира бита за знак в освободените позиции.

Когато са включени два операнда, местоназначението идва преди (отляво) източника (има някои изключения от това). Операционните кодове за асемблерния език ARM не са чувствителни към главни и малки букви.

Незабавен ARM64 режим на адресиране
Пример:

mov r0, #0xFF000000; Заредете 32-битовата стойност FF000000h в r0

Десетичната стойност е без 0x, но все пак е предшествана от #.

Регистрирайте се директно
Пример:

mov x0, x1; Копирайте x1 в x0

Регистрирайте индиректно
Пример:

str x0, [x3] ; Съхранявайте x0 на адреса в x3

Регистрирайте индиректно с отместване
Примери:

ldr x0, [x1, #32] ; Заредете r0 със стойността на адрес [r1+32]; r1 е основният регистър
str x0, [x1, #4] ; Съхранявайте r0 на адрес [r1+4]; r1 е основният регистър; числата са с основа 10

Регистрирайте индиректно с отместване (предварително увеличено)
Примери:

ldr x0, [x1, #32]! ; Заредете r0 с [r1+32] и актуализирайте r1 до (r1+32)
str x0, [x1, #4]! ; Съхранявайте r0 до [r1+4] и актуализирайте r1 до (r1+4)

Обърнете внимание на използването на '!' символ.

Регистрирайте индиректно с отместване (пост-инкрементирано)
Примери:

ldr x0, [x1], #32; Заредете [x1] до x0, след това актуализирайте x1 до (x1+32)
str x0, [x1], #4; Съхранявайте x0 до [x1], след което актуализирайте x1 до (x1+4)

Двоен регистър Индиректен
Адресът на операнда е сбор от основен регистър и регистър на нарастване. Имената на регистрите са оградени с квадратни скоби.
Примери:

ldr x0, [x1, x2] ; Заредете x0 с [x1+x2]
str x0, [rx, x2] ; Запазване на x0 до [x1+x2]

Режим на относително адресиране
В режим на относително адресиране ефективната инструкция е следващата инструкция в програмния брояч плюс индекс. Индексът може да бъде положителен или отрицателен.
Пример:

ldr x0, [pc, #24]

Това означава регистърът за зареждане X0 с думата, към която сочи съдържанието на компютъра, плюс 24.

6.44 Някои често използвани инструкции за ARM 64
Ето често използваните инструкции:

6.45 Лупинг

Илюстрация
Следният код продължава да добавя стойността в регистъра X10 към стойността в X9, докато стойността в X8 стане нула. Да приемем, че всички стойности са цели числа. Стойността в X8 се изважда с 1 при всяка итерация:

цикъл:
CBZ X8, пропуснете
ДОБАВЯНЕ на X9, X9, X10; първият X9 е дестинация, а вторият X9 е източник
SUB X8, X8, #1; първият X8 е дестинация, а вторият X8 е източник
B цикъл
пропуснете:

Както при 6502 µP и X64 µP, етикетът при ARM 64 µP започва в началото на реда. Останалите инструкции започват на няколко интервала след началото на реда. При x64 и ARM 64 етикетът е последван от двоеточие и нов ред. Докато при 6502 етикетът е последван от инструкция след интервал. В предишния код първата инструкция, която е „CBZ X8, пропусни“, означава, че ако стойността в X8 е нула, продължете към етикета „пропуснете:“, като пропуснете инструкциите между тях и продължете с останалите инструкции по-долу „пропускане:“. „B цикъл“ е безусловен скок към етикета „цикл“. Всяко друго име на етикет може да се използва вместо „цикъл“.

И така, както при 6502 µP, използвайте инструкциите за разклоняване, за да имате цикъл с ARM 64.

6.46 ARM 64 Вход/Изход
Всички ARM периферни устройства (вътрешни портове) са картографирани в паметта. Това означава, че интерфейсът за програмиране е набор от адресирани към паметта регистри (вътрешни портове). Адресът на такъв регистър е отместване от специфичен базов адрес на паметта. Това е подобно на начина, по който 6502 прави вход/изход. ARM няма опция за отделно I/O адресно пространство.

6.47 Стек от ARM 64
ARM 64 има стек в паметта (RAM) по подобен начин, по който имат 6502 и x64. При ARM64 обаче няма push или pop код за операция. Стекът в ARM 64 също расте надолу. Адресът в указателя на стека сочи точно след последния байт на последната стойност, която е поставена в стека.

Причината, поради която няма общ изскачащ или натискащ код за ARM64 е, че ARM 64 управлява своя стек в групи от последователни 16 байта. Стойностите обаче съществуват в байтови групи от един байт, два байта, четири байта и 8 байта. Така че една стойност може да бъде поставена в стека, а останалите места (местоположения на байтове), за да компенсират 16 байта, се допълват с фиктивни байтове. Това има недостатъка, че губи памет. По-добро решение е да попълните 16-байтовото местоположение с по-малки стойности и да накарате някакъв програмист да напише код, който проследява откъде идват стойностите в 16-байтовото местоположение (регистри). Този допълнителен код също е необходим за изтегляне на стойностите. Алтернатива на това е да попълните два 8-байтови регистъра с общо предназначение с различни стойности и след това да изпратите съдържанието на двата 8-байтови регистъра към стека. Тук все още е необходим допълнителен код за проследяване на специфичните малки стойности, които влизат в стека и напускат стека.

Следният код съхранява четири 4-байтови данни в стека:

str w0, [sp, #-4]!
str w1, [sp, #-8]!
str w2, [sp, #-12]!
str w3, [sp, #-16]!

Първите четири байта (w) от регистрите – x0, x1, x2 и x3 – се изпращат до 16-последователни байтови местоположения в стека. Обърнете внимание на използването на „str“, а не на „push“. Обърнете внимание на удивителния знак в края на всяка инструкция. Тъй като стекът на паметта расте надолу, първата четирибайтова стойност започва от позиция, която е минус четири байта под позицията на предишния указател на стека. Останалите четирибайтови стойности следват, като вървят надолу. Следният кодов сегмент ще направи правилния (и в ред) еквивалент на изваждане на четирите байта:

ldr w3, [sp], #0
ldr w2, [sp], #4
ldr w1, [sp], #8
ldr w0, [sp], #12

Обърнете внимание на използването на ldr opcode вместо pop. Също така имайте предвид, че символът на удивителния знак не се използва тук.

Всички байтове в X0 (8 байта) и X1 (8 байта) могат да бъдат изпратени до местоположението от 16 байта в стека, както следва:

stp x0, x1, [sp, #-16]! ; 8 + 8 = 16

В този случай регистрите x2 (w2) и x3 (w3) не са необходими. Всички желани байтове са в регистрите X0 и X2. Обърнете внимание на кода на операцията stp за съхраняване на двойките съдържание на регистъра в RAM. Обърнете внимание и на удивителния знак. Поп еквивалентът е:

ldp x0, x1, [sp], #0

За тази инструкция няма удивителен знак. Обърнете внимание на кода на операцията LDP вместо LDR за зареждане на две последователни местоположения с данни от паметта в два µP регистъра. Също така не забравяйте, че копирането от паметта в µP регистър е зареждане, което не трябва да се бърка със зареждането на файл от диска в RAM, а копирането от µP регистър в RAM е съхраняване.

6.48 Подпрограма
Подпрограмата е блок от код, който изпълнява задача, по избор въз основа на някои аргументи и по избор връща резултат. По конвенция регистрите от R0 до R3 (четири регистъра) се използват за предаване на аргументите (параметри) към подпрограма, а R0 се използва за предаване на резултат обратно на повикващия. Подпрограма, която се нуждае от повече от 4 входа, използва стека за допълнителните входове. За да извикате подпрограма, използвайте връзката или инструкцията за условно разклоняване. Синтаксисът за инструкцията за връзка е:

BL етикет

Където BL е кодът на операцията, а етикетът представлява началото (адреса) на подпрограмата. Това разклонение е безусловно, напред или назад в рамките на 128MB. Синтаксисът за инструкцията за условно разклоняване е:

B.cond етикет

Където cond е условието, напр. eq (равно) или ne (не е равно). Следната програма има подпрограмата doadd, която добавя стойностите на два аргумента и връща резултат в R0:

ОБЛАСТ подпроход, КОД, САМО ЗА ЧЕТЕНЕ; Назовете този блок от код
ВХОД ; Маркирайте първата инструкция за изпълнение
стартирайте MOV r0, #10; Настройте параметри
MOV r1, #3
BL добавяне; Извикване на подпрограма
спиране на MOV r0, #0x18; angel_SWIreason_ReportException
LDR r1, =0x20026; ADP_Stopped_ApplicationExit
SVC #0x123456; ARM полухостинг (бивш SWI)
doadd ДОБАВЯНЕ r0, r0, r1; Код на подпрограмата
BX lr ; Връщане от подпрограма
;
КРАЙ ; Маркирайте края на файла

Числата, които трябва да добавите, са десетична 10 и десетична 3. Първите два реда в този блок код (програма) ще бъдат обяснени по-късно. Следващите три реда изпращат 10 към регистър R0 и 3 към регистър R1 и също извикват подпрограмата doadd. „Doadd“ е етикетът, който съдържа адреса на началото на подпрограмата.

Подпрограмата се състои само от два реда. Първият ред добавя съдържанието 3 на R към съдържанието 10 на R0, което позволява резултатът от 13 в R0. Вторият ред с кода на операцията BX и операнд LR се връща от подпрограмата към кода на повикващия.

ДЯСНО
Операционният код RET в ARM 64 все още се занимава с подпрограмата, но работи различно от RTS в 6502 или RET на x64, или комбинацията „BX LR“ в ARM 64. В ARM 64 синтаксисът за RET е:

ПРАВ {Xn}

Тази инструкция дава възможност на програмата да продължи с подпрограма, която не е извикващата подпрограма, или просто да продължи с друга инструкция и нейния следващ кодов сегмент. Xn е регистър с общо предназначение, който съдържа адреса, към който програмата трябва да продължи. Тази инструкция се разклонява безусловно. По подразбиране е съдържание на X30, ако Xn не е дадено.

Стандартна процедура за повикване
Ако програмистът иска неговият код да взаимодейства с код, който е написан от някой друг или с код, който е произведен от компилатор, програмистът трябва да се съгласи с лицето или с автора на компилатора относно правилата за използване на регистъра. За ARM архитектурата тези правила се наричат ​​Procedure Call Standard или PCS. Това са споразумения между две или три страни. PCS уточнява следното:

  • Кои µP регистри се използват за предаване на аргументите във функцията (подпрограма)
  • Кои µP регистри се използват за връщане на резултата към функцията, която извършва извикването, което е известно като повикващия
  • Кой µP регистрира функцията, която се извиква, която е известна като callee, може да повреди
  • Кой µP регистрира извикваният не може да повреди

6.49 Прекъсвания
Има два типа вериги на контролера на прекъсванията, налични за ARM процесора:

  • Стандартен контролер за прекъсване: Манипулаторът за прекъсване определя кое устройство изисква обслужване чрез четене на растерния регистър на устройството в контролера за прекъсване.
  • Vector Interrupt Controller (VIC): Приоритизира прекъсванията и опростява определянето кое устройство е причинило прекъсването. След свързване на приоритет и адрес на манипулатор с всяко прекъсване, VIC подава сигнал за прекъсване към процесора само ако приоритетът на ново прекъсване е по-висок от текущо изпълняващия манипулатор на прекъсване.

Забележка : Изключението се отнася за грешка. Подробностите за векторния контролер за прекъсване за 32-битов компютър ARM са както следва (64 бита е подобен):

Таблица 6.49.1
ARM векторно изключение/прекъсване за 32-битов компютър
Изключение/Прекъсване Къса ръка Адрес Висок адрес
Нулиране НУЛИРАНЕ 0x00000000 0xffff0000
Недефинирана инструкция UNDEF 0x00000004 0xffff0004
Софтуерно прекъсване SWI 0x00000008 0xffff0008
Прекратяване на предварително извличане pabt 0x0000000C 0xffff000C
Дата на аборт DABT 0x00000010 0xffff0010
Запазено 0x00000014 0xffff0014
Искане за прекъсване IRQ 0x00000018 0xffff0018
Искане за бързо прекъсване FIQ 0x0000001C 0xffff001C

Това изглежда като подредбата за архитектурата 6502, където NMI , БР , и IRQ може да има указатели в нулева страница и съответните рутинни процедури са високо в паметта (ROM OS). Кратките описания на редовете от предишната таблица са както следва:

НУЛИРАНЕ
Това се случва, когато процесорът се включи. Той инициализира системата и настройва стековете за различни режими на процесора. Това е изключение с най-висок приоритет. При влизане в манипулатора за нулиране, CPSR е в режим SVC и битовете IRQ и FIQ са зададени на 1, маскирайки всички прекъсвания.

ДАТА НА АБОРТА
Вторият най-висок приоритет. Това се случва, когато се опитваме да четем/записваме на невалиден адрес или да получим грешно разрешение за достъп. При влизане в Data Abort Handler, IRQs ще бъдат деактивирани (I-bit set 1) и FIQ ще бъде активиран. IRQ са маскирани, но FIQ остават немаскирани.

FIQ
Прекъсването с най-висок приоритет, IRQ и FIQ, са забранени, докато не се обработи FIQ.

IRQ
Прекъсването с висок приоритет, IRQ манипулаторът, се въвежда само ако няма текущ FIQ и прекъсване на данни.

Прекратяване на предварително извличане
Това е подобно на прекъсване на данни, но се случва при неуспешно извличане на адрес. При влизане в манипулатора IRQ се деактивират, но FIQ остават активирани и могат да се случат по време на прекъсване на предварително извличане.

SWI
Изключение за софтуерно прекъсване (SWI) възниква, когато инструкцията SWI се изпълни и нито едно от другите изключения с по-висок приоритет не е маркирано.

Недефинирана инструкция
Изключението за недефинирана инструкция възниква, когато инструкция, която не е в набора инструкции ARM или Thumb, достигне етапа на изпълнение на конвейера и нито едно от другите изключения не е маркирано. Това е същият приоритет като SWI, тъй като един може да се случи наведнъж. Това означава, че инструкцията, която се изпълнява, не може едновременно да бъде SWI инструкция и недефинирана инструкция едновременно.

ARM обработка на изключения
Следните събития възникват, когато се случи изключение:

  • Съхранявайте CPSR в SPSR на режима на изключение.
  • PC се съхранява в LR на режим на изключение.
  • Регистърът на връзките е зададен на конкретен адрес въз основа на текущата инструкция. Например: за ISR, LR = последната изпълнена инструкция + 8.
  • Актуализирайте CPSR относно изключението.
  • Задайте на компютъра адреса на манипулатора на изключения.

6.5 Инструкции и данни

Данните се отнасят за променливи (етикети с техните стойности) и масиви и други структури, които са подобни на масива. Низът е като масив от знаци. Масив от цели числа се вижда в една от предишните глави. Инструкциите се отнасят до операционните кодове и техните операнди. Програмата може да бъде написана с кодовете за операции и данните, смесени в една продължаваща секция от паметта. Този подход има недостатъци, но не се препоръчва.

Програмата трябва да бъде написана първо с инструкциите, последвани от данните (множествено число от данни е данни). Разделянето между инструкциите и данните може да бъде само няколко байта. За една програма както инструкциите, така и данните могат да бъдат в една или две отделни секции в паметта.

6.6 Архитектурата на Харвард

Един от първите компютри се нарича Harvard Mark I (1944). Строгата архитектура на Харвард използва едно адресно пространство за програмни инструкции и различно отделно адресно пространство за данни. Това означава, че има две отделни памети. Следното показва архитектурата:


Фигура 6.71 Архитектура на Харвард

Контролният блок извършва декодирането на инструкциите. Аритметичната логическа единица (ALU) извършва аритметичните операции с комбинационна логика (портове). ALU извършва и логическите операции (напр. преместване).

С микропроцесора 6502 инструкция отива първо към микропроцесора (контролен блок), преди датата (единствено число за данни) да отиде в регистъра µP, преди те да взаимодействат. Това изисква поне два тактови импулса и не е едновременен достъп до инструкцията и данните. От друга страна, архитектурата на Харвард осигурява едновременен достъп до инструкциите и данните, като и инструкцията, и данните влизат в µP едновременно (операционен код към контролния блок и данните към µP регистъра), спестявайки поне един тактов импулс. Това е форма на паралелизъм. Тази форма на паралелизъм се използва в хардуерния кеш в съвременните дънни платки (вижте следващата дискусия).

6.7 Кеш памет

Кеш паметта (RAM) е високоскоростна област на паметта (в сравнение със скоростта на основната памет), която временно съхранява програмните инструкции или данни за бъдеща употреба. Кеш паметта работи по-бързо от основната памет. Обикновено тези инструкции или елементи с данни се извличат от скорошната основна памет и е вероятно скоро да са необходими отново. Основната цел на кеш паметта е да увеличи скоростта на многократен достъп до едни и същи места в основната памет. За да бъде ефективен, достъпът до кешираните елементи трябва да бъде значително по-бърз от достъпа до оригиналния източник на инструкциите или данните, който се нарича Backing Store.

Когато се използва кеширане, всеки опит за достъп до място в основната памет започва с търсене в кеша. Ако исканият елемент присъства, процесорът го извлича и използва незабавно. Това се нарича Cache Hit. Ако търсенето в кеша е неуспешно (пропуснат кеш), инструкцията или елементът с данни трябва да бъдат извлечени от резервното хранилище (основна памет). В процеса на извличане на заявения елемент, копие се добавя към кеша за очаквана употреба в близко бъдеще.

Блок за управление на паметта
Устройството за управление на паметта (MMU) е схема, която управлява основната памет и свързаните с нея регистри на паметта на дънната платка. В миналото това беше отделна интегрална схема на дънната платка; но днес той обикновено е част от микропроцесора. MMU трябва също така да управлява кеша (схемата), който днес също е част от микропроцесора. Кеш схемата е отделна интегрална схема в миналото.

Статична RAM памет
Статичната RAM (SRAM) има значително по-бързо време за достъп от DRAM, макар и за сметка на значително по-сложна схема. Битовите клетки на SRAM заемат много повече място върху матрицата на интегралната схема, отколкото клетките на DRAM устройство, което може да съхранява еквивалентно количество данни. Основната памет (RAM) обикновено се състои от DRAM (Dynamic RAM).

Кеш паметта подобрява производителността на компютъра, тъй като много алгоритми, които се изпълняват от операционни системи и приложения, показват локалността на препратката. Референтното местоположение се отнася до повторното използване на данни, които са били достъпни наскоро. Това се нарича Темпорална местност. На съвременната дънна платка кеш паметта е в същата интегрална схема като микропроцесора. Основната памет (DRAM) е далеч и е достъпна през шините. Референтното местоположение също се отнася до пространствено местоположение. Пространствената локализация е свързана с по-високата скорост на достъп до данни поради физическа близост.

Като правило областите на кеш паметта са малки (по брой байтове) в сравнение с резервното хранилище (основна памет). Устройствата с кеш памет са проектирани за максимална скорост, което обикновено означава, че те са по-сложни и скъпи на бит от технологията за съхранение на данни, която се използва в резервното хранилище. Поради ограничения си размер устройствата с кеш памет са склонни да се запълват бързо. Когато кешът няма налично място за съхраняване на нов запис, по-старият запис трябва да бъде изхвърлен. Кеш контролерът използва политика за заместване на кеша, за да избере кой запис в кеша ще бъде презаписан от новия запис.

Целта на кеш паметта на микропроцесора е да максимизира процента на попадения в кеша във времето, като по този начин осигурява най-високата устойчива скорост на изпълнение на инструкциите. За да постигне тази цел, логиката на кеша трябва да определи кои инструкции и данни ще бъдат поставени в кеша и запазени за близка бъдеща употреба.

Логиката за кеширане на процесора не гарантира, че даден елемент от кеширани данни ще бъде използван отново, след като бъде вмъкнат в кеша.

Логиката на кеширането разчита на вероятността, че поради времевата (повтаряща се във времето) и пространствената (пространствена) локалност, има много добър шанс за достъп до кешираните данни в близко бъдеще. При практически реализации на модерни процесори, кеш ударите обикновено се случват при 95 до 97 процента от достъпите до паметта. Тъй като латентността на кеш паметта е малка част от латентността на DRAM, високата честота на попадение в кеша води до значително подобрение на производителността в сравнение с дизайн без кеш.

Малко паралелизъм с кеша
Както бе споменато по-рано, добрата програма в паметта има инструкции, отделени от данните. В някои кеш системи има кеш верига от „ляво“ на процесора и има друга кеш верига от „дясно“ на процесора. Левият кеш обработва инструкциите на програма (или приложение), а десният кеш обработва данните на същата програма (или същото приложение). Това води до по-добра повишена скорост.

6.8 Процеси и нишки

Както CISC, така и RISC компютрите имат процеси. Има процес в софтуера. Програма, която работи (изпълнява се) е процес. Операционната система идва със собствени програми. Докато компютърът работи, програмите на операционната система, които позволяват работата на компютъра, също работят. Това са процеси на операционната система. Потребителят или програмистът може да пише свои собствени програми. Когато програмата на потребителя работи, това е процес. Няма значение дали програмата е написана на асемблер или на език от високо ниво като C или C++. Всички процеси (потребител или ОС) се управляват от друг процес, наречен „планировчик“.

Нишката е като подпроцес, принадлежащ на процес. Един процес може да започне и да се раздели на нишки и след това да продължи като един процес. Процес без нишки може да се счита за основна нишка. Процесите и техните нишки се управляват от един и същ планировчик. Самият планировчик е програма, когато е резидентен на диска на ОС. Когато работи в паметта, планировчикът е процес.

6.9 Многопроцесорна обработка

Нишките се управляват почти като процеси. Мултипроцесирането означава изпълнение на повече от един процес едновременно. Има компютри само с един микропроцесор. Има компютри с повече от един микропроцесор. С един микропроцесор процесите и/или нишките използват един и същ микропроцесор по начин на разплитане (или разделяне на времето). Това означава, че процесът използва процесора и спира, без да завърши. Друг процес или нишка използва процесора и спира, без да завърши. След това друг процес или нишка използва микропроцесора и спира без да завърши. Това продължава, докато всички процеси и нишки, които са поставени на опашка от планировчика, имат дял от процесора. Това се нарича едновременна многопроцесорна обработка.

Когато има повече от един микропроцесор, има паралелна мултипроцесорност, за разлика от паралелността. В този случай всеки процесор изпълнява определен процес или нишка, различен от това, което изпълнява другият процесор. Всички процесори на една и съща дънна платка изпълняват своите различни процеси и/или различни нишки едновременно в паралелна многопроцесорна обработка. Процесите и нишките в паралелната многопроцесорна обработка все още се управляват от планировчика. Паралелната мултипроцесорност е по-бърза от паралелната мултипроцесорност.

В този момент читателят може да се чуди как паралелната обработка е по-бърза от паралелната обработка. Това е така, защото процесорите споделят (трябва да използват по различно време) една и съща памет и входно/изходни портове. Е, с използването на кеша цялостната работа на дънната платка е по-бърза.

6.10 Пейджинг

Блокът за управление на паметта (MMU) е верига, която е близо до микропроцесора или в микропроцесорния чип. Той обработва картата на паметта или странирането и други проблеми с паметта. Нито 6502 µP, нито компютърът Commodore-64 имат MMU per se (въпреки че все още има известно управление на паметта в Commodore-64). Commodore-64 обработва паметта чрез страниране, където всяка страница е 256 10 дължина на байта (100 16 дълги байтове). Не беше задължително да обработва паметта чрез страниране. Все още може да има само карта на паметта и след това програми, които просто се вписват в различните си определени области. Е, странирането е един от начините за осигуряване на ефективно използване на паметта, без да има много секции на паметта, които не могат да имат данни или програма.

Компютърната архитектура x86 386 е пусната през 1985 г. Адресната шина е 32-битова. И така, общо 2 32 = 4,294,967,296 е възможно адресно пространство. Това адресно пространство е разделено на 1 048 576 страници = 1 024 KB страници. При този брой страници една страница се състои от 4096 байта = 4 KB. Следващата таблица показва страниците с физически адреси за 32-битовата архитектура x86:

Таблица 6.10.1
Физически адресируеми страници за x86 архитектурата
База 16 адреси Страници База 10 адреси
FFFFF000 – FFFFFFFF Страница 1,048,575 4,294,963,200 – 4,294,967,295
FFFFE000 – FFFFEFFF Страница 1,044,479 4,294,959,104 – 4,294,963,199
FFFFD000 – FFFFDFFF Страница 1,040,383 4,294,955,008 – 4,294,959,103
|
|
|
|
|
|
|
|
|
00002000 – 00002FFF Страница 2 8,192 – 12,288
00001000 – 00001FFF Страница 1 4 096 – 8 191
00000000 – 00000FFF Страница 0 0 – 4,095

Едно приложение днес се състои от повече от една програма. Една програма може да отнеме по-малко от страница (по-малко от 4096) или може да отнеме две или повече страници. Така едно приложение може да отнеме една или повече страници, като всяка страница е дълга 4096 байта. Различни хора могат да напишат приложение, като всеки човек е назначен за една или повече страници.

Забележете, че страница 0 е от 00000000H до 00000FFF
страница 1 е от 00001000H до 00001FFFH, страница 2 е от 00002000 з – 00002FFF з , и така нататък. За 32-битов компютър в процесора има два 32-битови регистъра за физическо адресиране на страници: един за базовия адрес, а другият за индексния адрес. За достъп до местоположенията на байтовете на страница 2, например, регистърът за основния адрес трябва да бъде 00002 з което е първите 20 бита (отляво) за началните адреси на страница 2. Останалите битове в диапазона от 000 з към FFF з са в регистъра, наречен „индексен регистър“. Така че всички байтове в страницата могат да бъдат достъпни чрез просто увеличаване на съдържанието в регистъра на индекса от 000 з към FFF з . Съдържанието в индексния регистър се добавя към съдържанието, което не се променя в основния регистър, за да се получи ефективният адрес. Тази схема за адресиране на индекса е вярна за другите страници.

Това обаче не е начинът, по който програмата на асемблерния език е написана за всяка страница. За всяка страница програмистът пише кода, започвайки от страница 000 з към страница FFF з . Тъй като кодът в различни страници е свързан, компилаторът използва адресирането на индекса, за да свърже всички свързани адреси в различни страници. Например, ако приемем, че страница 0, страница 1 и страница 2 са за едно приложение и всяка има 555 з адрес, който е свързан един с друг, компилаторът компилира по такъв начин, че когато 555 з на страница 0 е за достъп, 00000 з ще бъде в основния регистър и 555 з ще бъде в регистъра на индексите. Когато 555 з на страница 1 е за достъп, 00001 з ще бъде в основния регистър и 555 з ще бъде в регистъра на индексите. Когато 555 з на страница 2 е за достъп, 00002 з ще бъде в основния регистър, а 555H ще бъде в индексния регистър. Това е възможно, защото адресите могат да бъдат идентифицирани с помощта на етикети (променливи). Различните програмисти трябва да се споразумеят за името на етикетите, които да се използват за различните свързващи адреси.

Страница виртуална памет
Пейджингът, както беше описано по-горе, може да се модифицира, за да се увеличи размерът на паметта в техника, която се нарича „Виртуална памет на страницата“. Ако приемем, че всички страници с физическа памет, както е описано по-горе, имат нещо (инструкции и данни), не всички страници са активни в момента. Страниците, които в момента не са активни, се изпращат на твърдия диск и се заместват от страниците от твърдия диск, които трябва да се изпълняват. По този начин размерът на паметта се увеличава. Докато компютърът продължава да работи, страниците, които стават неактивни, се разменят със страниците в твърдия диск, които все още могат да бъдат страниците, изпратени от паметта към диска. Всичко това се извършва от модула за управление на паметта (MMU).

6.11 Проблеми

На читателя се препоръчва да реши всички задачи в дадена глава, преди да премине към следващата глава.

1) Посочете приликите и разликите на компютърните архитектури CISC и RISC. Назовете по един пример за SISC и RISC компютър.

2) а) Кои са следните имена за компютъра CISC по отношение на битовете: байт, дума, двойна дума, четворна дума и двойна четворна дума.
б) Какви са следните имена за компютъра RISC по отношение на битовете: байт, полудума, дума и двойна дума.
c) Да или Не. Двойната дума и четирикратната дума означават ли едни и същи неща както в CISC, така и в RISC архитектурите?

3 a) За x64 броят на байтовете за инструкциите на асемблерния език варира от какво до какво?
b) Броят на байтовете за всички инструкции на асемблерния език за ARM 64 фиксиран ли е? Ако да, какъв е броят на байтовете за всички инструкции?

4) Избройте най-често използваните инструкции за асемблер за x64 и техните значения.

5) Избройте най-често използваните инструкции за асемблер за ARM 64 и техните значения.

6) Начертайте обозначена блокова диаграма на стария компютър Harvard Architecture. Обяснете как неговите инструкции и функции за данни се използват в кеша на съвременните компютри.

7) Правете разлика между процес и нишка и дайте името на процеса, който управлява процесите и нишките в повечето компютърни системи.

8) Обяснете накратко какво е многопроцесорност.

9) a) Обяснете странирането като приложимо към компютърната архитектура x86 386 µP.
б) Как може да се модифицира това страниране, за да се увеличи размерът на цялата памет?