Глава 6: Основы современной компьютерной архитектуры с языком ассемблера

Glava 6 Osnovy Sovremennoj Komp Uternoj Arhitektury S Azykom Assemblera



6.1 Введение

Современные компьютеры общего назначения бывают двух типов: CISC и RISC. CISC означает «Компьютер со сложным набором команд». 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 Machine. Архитектура 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 мкП и компьютером Commodore-64, где это применимо.

6.2 Блок-схема материнской платы современного ПК

ПК означает персональный компьютер. Ниже приведена общая базовая блок-схема современной материнской платы с одним микропроцессором для персонального компьютера. Он представляет собой материнскую плату CISC или RISC.


Рис. 6.21 Базовая блок-схема материнской платы современного ПК

На схеме показаны три внутренних порта, но на практике их больше. У каждого порта есть регистр, который можно рассматривать как сам порт. Каждая схема порта имеет как минимум еще один регистр, который можно назвать «регистром состояния». Регистр состояния указывает порт программы, которая отправляет сигнал прерывания микропроцессору. Существует схема контроллера прерываний (не показана), которая различает разные линии прерываний от разных портов и имеет всего несколько линий к микропроцессору.

HD.C на схеме обозначает карту жесткого диска. NIC означает сетевую интерфейсную карту. Карта жесткого диска (схема) подключена к жесткому диску, который находится внутри базового блока (системного блока) современного компьютера. Сетевая карта (схема) подключена через внешний кабель к другому компьютеру. На схеме показан один порт и DMA (см. следующий рисунок), которые подключены к карте жесткого диска и/или сетевой интерфейсной карте. DMA означает прямой доступ к памяти.

Помните из главы о компьютере Commodore-64, что для отправки байтов из памяти на дисковод или другой компьютер каждый байт должен быть скопирован в регистр микропроцессора, прежде чем он будет скопирован в соответствующий внутренний порт, а затем автоматически к устройству. Чтобы получить байты с жесткого диска или другого компьютера в память, каждый байт должен быть скопирован из соответствующего регистра внутреннего порта в регистр микропроцессора перед копированием в память. Обычно это занимает много времени, если количество байтов в потоке велико. Решением для быстрой передачи является использование прямого доступа к памяти (схема) без прохождения через микропроцессор.

Цепь DMA находится между портом и HD. C или сетевая карта. При прямом доступе к памяти схемы DMA передача больших потоков байтов происходит непосредственно между схемой DMA и памятью (ОЗУ) без постоянного участия микропроцессора. DMA использует адресную шину и шину данных вместо µP. Общая продолжительность передачи короче, чем при использовании жесткого диска µP. И HD C., и NIC используют DMA, когда у них есть большой поток данных (байтов) для передачи в ОЗУ (память).

GPU означает графический процессор. Этот блок на материнской плате отвечает за отправку текста и движущихся или неподвижных изображений на экран.

В современных компьютерах (ПК) нет постоянного запоминающего устройства (ПЗУ). Однако существует BIOS или UEFI, который представляет собой своего рода энергонезависимую оперативную память. Информация в BIOS фактически сохраняется за счет батареи. Батарея — это то, что на самом деле поддерживает таймер часов в нужное время и дату для компьютера. UEFI был изобретен после BIOS и заменил BIOS, хотя BIOS по-прежнему весьма актуален для современных ПК. Мы обсудим это позже!

В современных ПК шины адреса и данных между микропроцессором и внутренними цепями портов (и памятью) не являются параллельными шинами. Это последовательные шины, которым нужны два проводника для передачи в одном направлении и еще два проводника для передачи в противоположном направлении. Это означает, например, что 32-битные данные можно отправлять последовательно (один бит за другим) в любом направлении.

Если последовательная передача осуществляется только в одном направлении по двум проводникам (двум линиям), это называется полудуплексной передачей. Если последовательная передача осуществляется в обоих направлениях по четырем проводникам, по одной паре в каждом направлении, это называется полнодуплексным.

Вся память современного компьютера по-прежнему состоит из ряда байтовых ячеек: восемь бит на байт. Современный компьютер имеет объем памяти не менее 4 гигабайт = 4 x 210 x 2. 10 х 2 10 = 4 х 1 073 741 824 10 байт = 4 х 1024 10/под> х 1024 10 х 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 есть некоторые различия. Информация в этом разделе предназначена для Intel.

В микропроцессоре 6502 регистр счетчика программ (недоступный напрямую), в котором хранится следующая выполняемая команда, имеет ширину 16 бит. Здесь (x64) счетчик программ называется указателем инструкций и имеет ширину 64 бита. Он обозначен как RIP. Это означает, что микропроцессор x64 может адресовать до 264 = 1,844674407 x 1019 (фактически 18 446 744 073 709 551 616) ячеек памяти. RIP не является регистром общего назначения.

Регистр указателя стека или RSP входит в число 16 регистров общего назначения. Он указывает на последнюю запись стека в памяти. Как и в случае с 6502 мкП, стек для x64 растет вниз. В x64 стек оперативной памяти используется для хранения адресов возврата подпрограмм. Он также используется для хранения «теневого пространства» (см. следующее обсуждение).

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

Таблица 6.31.1
Наиболее часто используемые флаги RFLAGS (биты)
Символ Кусочек Имя Цель
CF 0 Нести Он устанавливается, если арифметическая операция генерирует перенос или заимствование старшего бита результата; очищается в противном случае. Этот флаг указывает на состояние переполнения для арифметических операций с целыми числами без знака. Он также используется в арифметике с многократной точностью.
ПФ 2 Паритет Он устанавливается, если младший байт результата содержит четное количество битов 1; очищается в противном случае.
ИЗ 4 Регулировать Он устанавливается, если арифметическая операция генерирует перенос или заимствование бита 3 результата; очищается в противном случае. Этот флаг используется в двоично-десятичной (BCD) арифметике.
ЗФ 6 Нуль Он устанавливается, если результат равен нулю; очищается в противном случае.
Сан-Франциско 7 Знак Он устанавливается, если он равен старшему биту результата, который является знаковым битом целого числа со знаком (0 указывает на положительное значение, а 1 указывает на отрицательное значение).
ИЗ одиннадцать Переполнение Он устанавливается, если целочисленный результат является слишком большим положительным числом или слишком маленьким отрицательным числом (исключая знаковый бит), чтобы поместиться в операнде назначения; очищается в противном случае. Этот флаг указывает на состояние переполнения для арифметики целых чисел со знаком (дополнения до двух).
ДФ 10 Направление Он устанавливается, если выполняются инструкции строки направления (инкремент или декремент).
ИДЕНТИФИКАТОР двадцать один Идентификация Он устанавливается, если его изменчивость означает наличие инструкции CPUID.

В дополнение к восемнадцати 64-битным регистрам, которые были указаны ранее, микросхема архитектуры x64 имеет восемь 80-битных регистров для арифметики с плавающей запятой. Эти восемь регистров также можно использовать как регистры MMX (см. следующее обсуждение). Для XMM также имеется шестнадцать 128-битных регистров (см. следующее обсуждение).

Это еще не все о регистрах. Существует больше регистров x64, которые являются сегментными регистрами (в основном не используются в x64), регистрами управления, регистрами управления памятью, регистрами отладки, регистрами виртуализации, регистрами производительности, которые отслеживают все виды внутренних параметров (попадания/промахи в кэше, выполнение микроопераций, синхронизацию). , и многое другое).

SIMD

SIMD означает «Одна инструкция, несколько данных». Это означает, что одна инструкция языка ассемблера может одновременно обрабатывать несколько данных в одном микропроцессоре. Рассмотрим следующую таблицу:

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 не имеет ячеек памяти (нет банков оперативной памяти). Это разница в FFFF,0000,0000,000116, что довольно велико. В канонической старшей половине находится операционная система, а в канонической нижней половине — пользовательские программы (приложения) и данные. Операционная система состоит из двух частей: небольшой UEFI (BIOS) и большой части, загружаемой с жесткого диска. В следующей главе больше говорится о современных операционных системах. Обратите внимание на сходство этой карты памяти и карты Commodore-64, когда 64 КБ могли выглядеть как большой объем памяти.

В этом контексте операционную систему грубо называют «ядром». Ядро похоже на ядро ​​компьютера Commodore-64, но имеет гораздо больше подпрограмм.

Порядок байтов для x64 имеет прямой порядок байтов, что означает, что для местоположения младший адрес указывает на младший байт содержимого в памяти.

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 (copy) x64 может сочетать как косвенную, так и индексированную адресацию. Пример:

МОВ 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:

МОВ АЛ, [RIP]

AL в RAX имеет 8-битное число со знаком, которое добавляется или вычитается из содержимого RIP (64-битный указатель инструкции), чтобы указать на следующую инструкцию. Обратите внимание, что в этой инструкции источник и назначение меняются местами в исключительных случаях. Также обратите внимание на использование квадратных скобок, которые относятся к содержимому RIP.

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

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

Таблица 6.34.1
Часто используемые инструкции в x64
Код операции Значение
МОВ Перемещение (копирование) в/из/между памятью и регистрами
ЦМОВ* Различные условные ходы
XCHG Обмен
БСВАП Замена байтов
ПУШ/ПОП Использование стека
ДОБАВИТЬ/АЦП Добавить/с переносом
СУБ/SBC Вычитание/с переносом
МУЛ/ИМУЛ Умножение/без знака
ДИВ/ИДИВ Разделить/без знака
ИНК/ДЕКАБРЬ Увеличение/Уменьшение
НЕГ Отрицать
КМП Сравнивать
И/ИЛИ/ИСКЛЮЧАЮЩЕЕ ИЛИ/НЕ Побитовые операции
ШР/САР Сдвиг вправо, логика/арифметика
ШЛ/САЛ Сдвиг влево логическое/арифметическое
РОР/РОЛЬ Поворот вправо/влево
РКР/РКЛ Поворот вправо/влево с помощью переносного бита
БТ/БТС/БТР Проверка бита/и установка/и сброс
СПМ Безусловный прыжок
JE/JNE/JC/JNC/J* Прыгать, если равно/не равно/переносить/не переносить/многие другие
ХОДИТЬ/ХОДИТЬ/ХОДИТЬ Цикл с ECX
ВЫЗОВ/ВОЗВРАТ Вызов подпрограммы/возврат
НЕТ Нет операции
идентификатор процессора Информация о процессоре

В x64 есть инструкции умножения и деления. В его микропроцессоре имеются аппаратные схемы умножения и деления. 6502 µP не имеет аппаратных схем умножения и деления. Аппаратное умножение и деление выполняется быстрее, чем программное (включая сдвиг битов).

Строковые инструкции
Существует несколько строковых инструкций, но здесь будет рассмотрена единственная инструкция MOVS (для перемещения строки), позволяющая копировать строку, начиная с адреса C000. ЧАС . Начать с адреса C100 ЧАС , используйте следующую инструкцию:

МОВС [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 раз (читайте комментарии):

ДВИЖЕНИЕ EAX, 0 ;
МОВ ЭКХ, 10 ; по умолчанию обратный отсчет 10 раз, один раз для каждой итерации
этикетка:
ВКЛ EAX ; увеличить EAX как тело цикла
метка ПЕТЛЯ ; уменьшить EAX, и если EAX не равен нулю, повторно выполнить тело цикла из «label:»

Кодирование цикла начинается с «метки:». Обратите внимание на использование двоеточия. Кодирование цикла заканчивается меткой LOOP, которая указывает на уменьшение EAX. Если его содержимое не равно нулю, вернитесь к инструкции после «метки:» и повторно выполните любую инструкцию (все инструкции тела), которая идет вниз, до «метки LOOP». Обратите внимание, что «метка» может иметь другое имя.

6.36 Ввод/вывод x64

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

Информация может передаваться между процессором и внутренним портом двумя способами: с использованием так называемого ввода-вывода с отображением в памяти или с использованием отдельного адресного пространства ввода-вывода. Ввод-вывод, отображаемый в памяти, аналогичен тому, что происходит с процессором 6502, где адреса портов фактически являются частью всего пространства памяти. В этом случае при отправке данных по определенному адресу они попадают в порт, а не в банк памяти. Порты могут иметь отдельное адресное пространство ввода-вывода. В последнем случае адреса всех банков памяти начинаются с нуля. Существует отдельный диапазон адресов от 0000H до FFFF16. Они используются портами чипсета. Материнская плата запрограммирована так, чтобы не путать ввод-вывод, отображаемый в памяти, и отдельное адресное пространство ввода-вывода.

Ввод-вывод, отображаемый в памяти
При этом порты рассматриваются как ячейки памяти, а для передачи данных между микропроцессором и портами используются обычные коды операций, используемые между памятью и микропроцессором. Итак, чтобы переместить байт из порта по адресу F000H в регистр µP RAX:EAX:AX:AL, сделайте следующее:

ДВИЖЕНИЕ АЛ, [F000H]

Строку можно переместить из памяти в порт и наоборот. Пример:

МОВС [F000H], [C000H] ; источник — C000H, а пункт назначения — порт F000H.

Отдельное адресное пространство ввода-вывода

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

Перенос отдельных элементов
Регистром процессора для передачи является RAX. На самом деле это RAX:EAX для двойного слова, RAX:EAX:AX ​​для слова и RAX:EAX:AX:AL для байта. Итак, чтобы передать байт из порта FFF0h в RAX:EAX:AX:AL, введите следующее:

В АЛ, [FFF0H]

Для обратного перевода введите следующее:

ВЫХОД [FFF0H], АЛ

Итак, для отдельных элементов используются инструкции IN и OUT. Адрес порта также может быть указан в регистре RDX:EDX:DX.

Перенос строк
Строку можно передать из памяти в порт чипсета и наоборот. Чтобы передать строку из порта по адресу FFF0H в память, начните с C100H, введите:

ИНС [ESI], [DX]

который имеет тот же эффект, что и:

ИНС [EDI], [DX]

Программист должен поместить двухбайтовый адрес порта FFF0H в регистр RDX:EDX:Dx и двухбайтовый адрес C100H в регистр RSI:ESI или RDI:EDI. Для обратного переноса выполните следующие действия:

ИНС [DX], [ESI]

который имеет тот же эффект, что и:

ИНС [DX], [EDI]

6.37 Стек в x64

Как и процессор 6502, процессор x64 также имеет стек в оперативной памяти. Стек для x64 может быть 2 16 = 65 536 байт или может быть 2 32 = 4 294 967 296 байт. Он также растет вниз. Когда содержимое регистра помещается в стек, число в указателе стека RSP уменьшается на 8. Помните, что адрес памяти для x64 имеет ширину 64 бита. Значение указателя стека в микропроцессоре указывает на следующую ячейку стека в ОЗУ. Когда содержимое регистра (или значение одного операнда) извлекается из стека в регистр, число в указателе стека RSP увеличивается на 8. Операционная система определяет размер стека и место его начала в ОЗУ. и растет вниз. Помните, что стек — это структура «последним пришел — первым обслужен» (LIFO), которая в данном случае растет вниз и сжимается вверх.

Чтобы поместить содержимое регистра µP RBX в стек, выполните следующие действия:

НАЖМИТЕ РБКС

Чтобы вернуть последнюю запись в стеке обратно в RBX, выполните следующие действия:

POP-RBX

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

Подпрограмма в x64 называется «процедура». Стек здесь используется больше, чем в 6502 мкП. Синтаксис процедуры x64:

имя_процесса:
тело процедуры

верно

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

ВЫЗОВ имя_процесса

В модели 6502 имя метки достаточно просто ввести для вызова. Однако здесь набирается зарезервированное слово «CALL» или «call», за которым после пробела следует имя процедуры (подпрограммы).

Когда речь идет о процедурах, обычно существует две процедуры. Одна процедура вызывает другую. Процедура, которая вызывает (имеет инструкцию вызова), называется «вызывающей», а вызываемая процедура называется «вызываемой». Существует соглашение (правила), которому нужно следовать.

Правила звонящего

При вызове подпрограммы вызывающая сторона должна соблюдать следующие правила:

1. Перед вызовом подпрограммы вызывающая сторона должна сохранить в стек содержимое определенных регистров, которые обозначены как сохраняемые вызывающей стороной. Регистры, сохраняемые вызывающей стороной, — это R10, R11 и любые регистры, в которые помещаются параметры (RDI, RSI, RDX, RCX, R8, R9). Если содержимое этих регистров должно сохраняться при вызове подпрограммы, поместите его в стек, а не сохраняйте затем в ОЗУ. Это необходимо сделать, поскольку вызываемая сторона должна использовать регистры для стирания предыдущего содержимого.

2. Если процедура заключается, например, в добавлении двух чисел, эти два числа являются параметрами, которые должны быть переданы в стек. Чтобы передать параметры в подпрограмму, поместите шесть из них в следующие регистры по порядку: RDI, RSI, RDX, RCX, R8, R9. Если в подпрограмме имеется более шести параметров, остальные помещаются в стек в обратном порядке (т. е. сначала последний параметр). Поскольку стек растет вниз, первый из дополнительных параметров (на самом деле седьмой параметр) сохраняется по наименьшему адресу (эта инверсия параметров исторически использовалась, чтобы позволить функциям (подпрограммам) передаваться с переменным количеством параметров).

3. Для вызова подпрограммы (процедуры) используйте инструкцию вызова. Эта инструкция помещает адрес возврата поверх параметров в стеке (самая нижняя позиция) и перехода к коду подпрограммы.

4. После возврата из подпрограммы (т. е. сразу после инструкции вызова) вызывающая сторона должна удалить из стека все дополнительные параметры (помимо шести, которые хранятся в регистрах). Это восстанавливает стек в его состояние до выполнения вызова.

5. Вызывающий может рассчитывать найти возвращаемое значение (адрес) подпрограммы в регистре RAX.

6. Вызывающий объект восстанавливает содержимое сохраненных им регистров (R10, R11 и любых регистров передачи параметров), извлекая их из стека. Вызывающая программа может предположить, что никакие другие регистры не были изменены подпрограммой.

Из-за структуры соглашения о вызовах обычно некоторые (или большинство) этих шагов не вносят никаких изменений в стек. Например, если имеется шесть или меньше параметров, на этом этапе в стек ничего не помещается. Аналогично, программисты (и компиляторы) обычно сохраняют результаты, которые им интересны, в регистрах, сохраненных вызывающей стороной на шагах 1 и 6, чтобы предотвратить чрезмерные операции push и pop.

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

Правила вызываемого абонента

Определение вызываемой подпрограммы должно соответствовать следующим правилам:

1. Выделите локальные переменные (переменные, создаваемые внутри процедуры), используя регистры или освобождая место в стеке. Напомним, что стек растет вниз. Итак, чтобы освободить место на вершине стека, указатель стека должен быть уменьшен. Величина, на которую уменьшается указатель стека, зависит от необходимого количества локальных переменных. Например, если требуются локальное число с плавающей запятой и локальное длинное значение (всего 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. Третий
; параметр находится в ячейке памяти «переменная»

нажать RDI; rdi будет параметром, поэтому сохраните его
; длинный retVal = myFunc (x, 456, z);

мов рди, ракс; поместите первый параметр в RDI
мов рси, 456 ; поместите второй параметр в RSI
mov rdx, [переменная]; поместите третий параметр в RDX

вызвать myFunc; вызвать функцию

поп-рди; восстановить сохраненное значение RDI
; возвращаемое значение myFunc теперь доступно в RAX

Пример вызываемой функции (myFunc) (читайте комментарии):

мояФунк:
; ∗∗∗ Пролог стандартной подпрограммы ∗∗∗
суб-рсп, 8; место для 64-битной локальной переменной (результат) с использованием кода операции «sub»

нажать rbx; сохранить вызываемого абонента — сохранить регистры
нажать РБП ; оба будут использоваться myFunc

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

; ∗∗∗ Эпилог стандартной подпрограммы ∗∗∗
поп-рбп; восстановить регистры вызываемого абонента
поп-рбх; наоборот, когда нажимаешь
добавить рсп, 8 ; освободить локальную переменную(и). 8 означает 8 байт
РЭТ; вытащить верхнее значение из стека и перейти туда

6.39 Прерывания и исключения для x64

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

  • Прерывание — это асинхронное (может произойти в любое время) событие, которое обычно инициируется устройством ввода-вывода.
  • Исключением является синхронное событие (происходит при выполнении кода, предварительно запрограммированное на основе какого-либо события), которое генерируется, когда процессор обнаруживает одно или несколько предопределенных условий во время выполнения инструкции. Определены три класса исключений: ошибки, ловушки и прерывания.

Процессор реагирует на прерывания и исключения практически одинаково. Когда сигнализируется прерывание или исключение, процессор останавливает выполнение текущей программы или задачи и переключается на процедуру-обработчик, написанную специально для обработки состояния прерывания или исключения. Процессор обращается к процедуре-обработчику через запись в таблице дескрипторов прерываний (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 используется прямой порядок байтов, который обычно используется операционными системами. 64-битная архитектура ARM является современной и призвана заменить 32-битную архитектуру ARM.

Примечание : Каждая инструкция для 64-битного ARM µP имеет длину 4 байта (32 бита).

6.41. Набор 64-битных регистров ARM.
Для 64-битного ARM µP имеется 31 64-битный регистр общего назначения. На следующей диаграмме показаны регистры общего назначения и некоторые важные регистры:


Рис.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. В этом регистре хранятся флаги, которые используются для результатов операций и для управления процессором (мкП). Его ширина составляет 32 бита. В следующей таблице приведены имена, индексы и значения часто используемых битов в регистре PSTATE:

Таблица 6.41.1
Наиболее используемые флаги PSTATE (биты)
Символ Кусочек Цель
М 0-3 Режим: текущий уровень привилегий выполнения (USR, SVC и т. д.).
Т 4 Thumb: устанавливается, если активен набор команд T32 (Thumb). Если флажок снят, набор инструкций ARM активен. Код пользователя может устанавливать и очищать этот бит.
И 9 Порядок байтов: установка этого бита включает режим прямого порядка байтов. Если этот флажок установлен, активен режим прямого порядка байтов. По умолчанию используется режим с прямым порядком байтов.
вопрос 27 Флаг совокупного насыщения: устанавливается, если в какой-то момент серии операций происходит переполнение или насыщение.
В 28 Флаг переполнения: устанавливается, если операция привела к знаковому переполнению.
С 29 Флаг переноса: указывает, привело ли сложение к переносу или к заимствованию при вычитании.
С 30 Флаг нуля: устанавливается, если результат операции равен нулю.
Н 31 Отрицательный флаг: устанавливается, если результат операции отрицательный.

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

SIMD
SIMD означает «Одна инструкция, несколько данных». Это означает, что одна инструкция языка ассемблера может одновременно обрабатывать несколько данных в одном микропроцессоре. Имеется тридцать два регистра шириной 128 бит для использования с SIMD и операциями с плавающей запятой.

6.42 Отображение памяти
RAM и DRAM являются памятью с произвольным доступом. DRAM работает медленнее, чем RAM. DRAM дешевле оперативной памяти. Если в памяти имеется более 32 гигабайт (ГБ) постоянной DRAM, возникнет больше проблем с управлением памятью: 32 ГБ = 32 x 1024 x 1024 x 1024 байта. Для всего объема памяти, который намного превышает 32 ГБ, DRAM выше 32 ГБ следует чередовать с ОЗУ для лучшего управления памятью. Чтобы понять карту памяти ARM-64, вам следует сначала понять карту памяти объемом 4 ГБ для 32-битного центрального процессора (ЦП) ARM. ЦП означает микропроцессор. Для 32-битного компьютера максимальное адресное пространство памяти равно 2 32 = 4 х 2 10 х 2 10 х 2 10 = 4 х 1024 х 1024 х 1024 = 4 294 967 296 = 4 ГБ.

32-битная карта памяти ARM
Карта памяти для 32-битного ARM:

Для 32-битного компьютера максимальный размер всей памяти составляет 4 ГБ. От адреса 0 ГБ до адреса 1 ГБ расположены операционная система ПЗУ, ОЗУ и места ввода-вывода. Вся идея ПЗУ, ОЗУ и адресов ввода-вывода аналогична ситуации с Commodore-64 с возможным процессором 6502. ПЗУ ОС Commodore-64 находится в верхней части памяти. ПЗУ здесь значительно больше, чем у Commodore-64, и находится в начале всего адресного пространства памяти. Если сравнивать с другими современными компьютерами, то ПЗУ ОС здесь полное, в том смысле, что оно сравнимо с объемом ОС на их жестких дисках. Есть две основные причины наличия ОС в интегральных схемах ПЗУ: 1) Процессоры ARM в основном используются в небольших устройствах, таких как смартфоны. Многие жесткие диски больше, чем смартфоны и другие небольшие устройства, 2) из ​​соображений безопасности. Когда ОС находится в памяти только для чтения, хакеры не могут повредить ее (части перезаписать). Разделы оперативной памяти и разделы ввода/вывода также очень большие по сравнению с таковыми у Commodore-64.

При включении питания с 32-битной ОС ПЗУ ОС должна запускаться (загружаться с) по адресу 0x00000000 или по адресу 0xFFFF0000, если включен HiVEC. Таким образом, когда питание включается после фазы сброса, аппаратное обеспечение ЦП загружает 0x00000000 или 0xFFFF0000 в счетчик программ. Префикс «0x» означает шестнадцатеричный формат. Загрузочный адрес 64-битных процессоров ARMv8 является определенной реализацией. Однако автор советует компьютерному инженеру начинать с 0x00000000 или 0xFFFF0000 ради обратной совместимости.

От 1 ГБ до 2 ГБ — это сопоставленный ввод/вывод. Существует разница между отображаемым вводом-выводом и просто вводом-выводом, который находится между 0 ГБ и 1 ГБ. При вводе-выводе адрес каждого порта фиксирован, как и в Commodore-64. При сопоставленном вводе-выводе адрес каждого порта не обязательно одинаков для каждой операции компьютера (динамический).

От 2 до 4 ГБ — это DRAM. Это ожидаемая (или обычная) оперативная память. DRAM означает динамическое ОЗУ, но это не означает изменение адреса во время работы компьютера, а означает, что значение каждой ячейки в физическом ОЗУ должно обновляться при каждом тактовом импульсе.

Примечание :

  • От 0x0000,0000 до 0x0000 FFFF — это ПЗУ ОС.
  • От 0x0001,0000 до 0x3FFF,FFFF может быть больше ПЗУ, затем ОЗУ, а затем немного ввода-вывода.
  • От 0x4000,0000 до 0x7FFF,FFFF разрешен дополнительный ввод-вывод и/или сопоставленный ввод-вывод.
  • От 0x8000,0000 до 0xFFFF FFFF — это ожидаемый DRAM.

Это означает, что на практике ожидаемый размер DRAM не обязательно должен начинаться с границы памяти в 2 ГБ. Почему программист должен соблюдать идеальные границы, если на материнской плате недостаточно банков физической памяти? Это связано с тем, что у клиента не хватает денег на все банки ОЗУ.

36-битная карта памяти ARM
В 64-битном компьютере ARM все 32 бита используются для адресации всей памяти. Для 64-битного компьютера ARM первые 36 бит могут использоваться для адресации всей памяти, которая в данном случае равна 2 36 = 68 719 476 736 = 64 ГБ. Это уже много памяти. Обычным компьютерам сегодня не нужен такой объем памяти. Это еще не максимальный диапазон памяти, к которому могут обращаться 64 бита. Карта памяти для 36-битного процессора ARM:

От адреса 0 ГБ до адреса 4 ГБ — это 32-битная карта памяти. «Зарезервировано» означает, что оно не используется и сохраняется для использования в будущем. Это не обязательно должны быть банки физической памяти, установленные на материнской плате для этого места. Здесь DRAM и отображаемый ввод-вывод имеют то же значение, что и 32-битная карта памяти.

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

  • 0x1 0000 0000 – 0x3 FFFF FFFF; сдержанный. 12 ГБ адресного пространства зарезервировано для использования в будущем.
  • 0x4 0000 0000 – 0x7 FFFF FFFF; сопоставленный ввод-вывод. Для динамически отображаемого ввода-вывода доступно 16 ГБ адресного пространства.
  • 0x8 0000 0000 – 0x8 7FFF FFFF FFFF; Дырка или DRAM. 2 ГБ адресного пространства могут содержать одно из следующего:
    • Отверстие для включения разделения устройств DRAM (как описано в следующем обсуждении).
    • ДРАМ.
  • 0x8 8000 0000 – 0xF FFFF FFFF; ДРАМ. 30 ГБ адресного пространства для DRAM.

Эта карта памяти представляет собой надмножество 32-битной карты адресов, в которой дополнительное пространство разделено на 50% DRAM (1/2) с необязательным отверстием в нем и 25% отображаемого пространства ввода-вывода и зарезервированного пространства (1/4 ). Остальные 25% (1/4) предназначены для 32-битной карты памяти ½ + ¼ + ¼ = 1.

Примечание : От 32 бит до 360 бит — это прибавление 4 бит к старшей стороне 36 бит.

40-битная карта памяти
40-битная карта адресов представляет собой надмножество 36-битной карты адресов и соответствует той же схеме: 50% DRAM с дополнительным отверстием в ней, 25% отображаемого пространства ввода-вывода и зарезервированного пространства, а остальные 25% место для предыдущей карты памяти (36-бит). Схема карты памяти следующая:

Размер дырки 544 – 512 = 32Гб. На практике можно встретить следующую ситуацию:

  • 0x10 0000 0000 – 0x3F FFFF FFFF; сдержанный. 192 ГБ адресного пространства зарезервировано для использования в будущем.
  • 0x40 0000 0000 – 0x7F FFFF FFFF; нанесено на карту. Ввод-вывод 256 ГБ адресного пространства доступно для динамически отображаемого ввода-вывода.
  • 0x80 0000 0000 – 0x87 FFFF FFFF; отверстие или DRAM. 32 ГБ адресного пространства могут содержать одно из следующего:
    • Отверстие для включения разделения устройств DRAM (как описано в следующем обсуждении).
    • ДРАМ
  • 0x88 0000 0000 – 0xFF FFFF FFFF; ДРАМ. 480 ГБ адресного пространства для DRAM.

Примечание : От 36 бит до 40 бит — это прибавление 4 бит к старшей стороне 36 бит.

Отверстие для оперативной памяти
В карте памяти за пределами 32-бит это либо дыра DRAM, либо продолжение DRAM сверху. Когда это дыра, ее следует понимать следующим образом: Дыра DRAM позволяет разделить большое устройство DRAM на несколько диапазонов адресов. Дополнительное отверстие DRAM предлагается в начале границы верхнего адреса DRAM. Это обеспечивает упрощенную схему декодирования при разделении устройства DRAM большой емкости по нижней физически адресуемой области.

Например, часть DRAM объемом 64 ГБ подразделяется на три области, причем смещения адресов выполняются путем простого вычитания старших битов адреса следующим образом:

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

Предлагаемые 44-битные и 48-битные адресные карты памяти для процессоров ARM
Предположим, что персональный компьютер имеет 1024 ГБ (= 1 ТБ) памяти; это слишком много памяти. А так, 44-битная и 48-битная адресные карты памяти для процессоров ARM на 16 ТБ и 256 ТБ соответственно — это всего лишь предложения для будущих компьютерных нужд. Фактически, эти предложения для процессоров ARM следуют тому же разделению памяти по соотношению, что и предыдущие карты памяти. То есть: 50% DRAM с дополнительным отверстием, 25% отображаемого пространства ввода-вывода и зарезервированного пространства, а остальные 25% пространства для предыдущей карты памяти.

52-битные, 56-битные, 60-битные и 64-битные карты адресуемой памяти еще предстоит предложить для 64-битного ARM в далеком будущем. Если ученые того времени все еще находят разделение всего пространства памяти 50:25:25 полезным, они сохранят это соотношение.

Примечание : SoC означает «система-на-кристалле», что относится к схемам в микросхеме µP, которых в противном случае там не было бы.

SRAM или статическая оперативная память быстрее, чем более традиционная DRAM, но требует большей площади кремния. SRAM не требует обновления. Читатель может представить ОЗУ как 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, но ему по-прежнему предшествует #.

Зарегистрироваться Директ
Пример:

переместить х0, х1 ; Скопировать x1 в x0

Зарегистрироваться косвенно
Пример:

ул x0, [x3] ; Сохраните x0 по адресу в x3

Регистрация косвенная со смещением
Примеры:

лдр x0, [x1, #32] ; Загрузите в r0 значение по адресу [r1+32]; r1 — базовый регистр
ул x0, [x1, #4] ; Сохраните r0 по адресу [r1+4]; r1 — базовый регистр; числа имеют основание 10

Косвенная регистрация со смещением (с предварительным приращением)
Примеры:

лдр x0, [x1, #32]! ; Загрузите в r0 значение [r1+32] и обновите r1 до (r1+32).
ул x0, [x1, #4]! ; Сохраните r0 в [r1+4] и обновите r1 до (r1+4).

Обратите внимание на использование знака «!» символ.

Косвенная регистрация со смещением (с последующим приращением)
Примеры:

лдр x0, [x1], #32 ; Загрузите [x1] в x0, затем обновите x1 до (x1+32)
ул x0, [x1], #4 ; Сохраните x0 в [x1], затем обновите x1 до (x1+4).

Двойной регистр косвенный
Адрес операнда представляет собой сумму базового регистра и регистра приращения. Имена регистров заключаются в квадратные скобки.
Примеры:

лдр x0, [x1, x2] ; Загрузите x0 с помощью [x1+x2]
стр x0, [rx, x2] ; Сохраните x0 в [x1+x2]

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

лдр x0, [ПК, #24]

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

6.44 Некоторые часто используемые инструкции для ARM 64
Вот часто используемые инструкции:

6.45 Циклическое выполнение

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

петля:
CBZ X8, пропустить
ДОБАВИТЬ X9, X9, X10 ; первый X9 — пункт назначения, второй X9 — источник.
СУБ X8, X8, #1 ; первый X8 — пункт назначения, второй X8 — источник.
Петля Б
пропускать:

Как и в случае с 6502 мкП и X64 мкП, метка в ARM 64 мкП начинается в начале строки. Остальные инструкции начинаются через несколько пробелов после начала строки. В x64 и ARM 64 за меткой следует двоеточие и новая строка. В то время как в случае с 6502 за меткой следует инструкция после пробела. В предыдущем коде первая инструкция «CBZ X8, пропустить» означает, что если значение в X8 равно нулю, продолжить с метки «skip:», пропуская промежуточные инструкции и переходя к остальным инструкциям ниже. 'пропускать:'. «Петля Б» — это безусловный переход к метке «Петля». Вместо «loop» можно использовать любое другое имя метки.

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

6.46 ARM 64 Вход/Выход
Все периферийные устройства ARM (внутренние порты) отображаются в памяти. Это означает, что интерфейс программирования представляет собой набор регистров, адресованных памяти (внутренних портов). Адрес такого регистра представляет собой смещение от определенного базового адреса памяти. Это похоже на то, как 6502 выполняет ввод/вывод. ARM не имеет возможности отдельного адресного пространства ввода-вывода.

6.47 Стек ARM 64
У ARM 64 стек в памяти (ОЗУ) аналогичен тому, что есть у 6502 и x64. Однако в ARM64 нет кода операции push или pop. Стек в ARM 64 также растет вниз. Адрес в указателе стека указывает сразу после последнего байта последнего значения, помещенного в стек.

Причина, по которой для ARM64 не существует общего кода операции pop или push, заключается в том, что 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». Обратите внимание на восклицательный знак в конце каждой инструкции. Поскольку стек памяти растет вниз, первое четырехбайтовое значение начинается с позиции, которая на минус четыре байта ниже предыдущей позиции указателя стека. Остальные четырехбайтовые значения следуют вниз. Следующий сегмент кода выполнит правильный (и по порядку) эквивалент извлечения четырех байтов:

лдр w3, [sp], #0
лдр w2, [sp], #4
лдр w1, [sp], #8
лдр w0, [sp], #12

Обратите внимание на использование кода операции ldr вместо pop. Также обратите внимание, что здесь не используется восклицательный знак.

Все байты в X0 (8 байт) и X1 (8 байт) могут быть отправлены в 16-байтовое место в стеке следующим образом:

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

В этом случае регистры х2(w2) и х3(w3) не нужны. Все нужные байты находятся в регистрах X0 и X2. Обратите внимание на код операции stp для сохранения пар содержимого регистров в ОЗУ. Также обратите внимание на восклицательный знак. Поп-эквивалент:

лдп x0, x1, [sp], #0

В этой инструкции нет восклицательного знака. Обратите внимание на код операции LDP вместо LDR для загрузки двух последовательных ячеек данных из памяти в два регистра µP. Также помните, что копирование из памяти в регистр µP — это загрузка, не путать с загрузкой файла с диска в ОЗУ, а копирование из регистра µP в ОЗУ — это сохранение.

6.48 Подпрограмма
Подпрограмма — это блок кода, который выполняет задачу (необязательно на основе некоторых аргументов) и необязательно возвращает результат. По соглашению, регистры от R0 до R3 (четыре регистра) используются для передачи аргументов (параметров) подпрограмме, а R0 используется для передачи результата обратно вызывающей программе. Подпрограмма, которой требуется более 4 входных данных, использует стек для дополнительных входных данных. Для вызова подпрограммы используйте ссылку или инструкцию условного перехода. Синтаксис инструкции ссылки:

Этикетка BL

Где BL — код операции, а метка — начало (адрес) подпрограммы. Эта ветвь является безусловной, вперед или назад в пределах 128 МБ. Синтаксис инструкции условного перехода следующий:

Метка B.cond

Где cond — это условие, например, eq (равен) или ne (не равен). В следующей программе есть функция doadd, которая складывает значения двух аргументов и возвращает результат в R0:

AREA subrout, CODE, READONLY ; Назовите этот блок кода
ВХОД ; Отметить первую инструкцию для выполнения
запустить MOV r0, #10 ; Настройка параметров
МОВ r1, #3
BL добавить ; Вызов подпрограммы
остановить MOV r0, #0x18 ; angel_SWIreason_ReportException
ЛДР r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456; Полухостинг ARM (ранее SWI)
doadd ADD r0, r0, r1 ; Код подпрограммы
ВХ лр ; Возврат из подпрограммы
;
КОНЕЦ ; Отметить конец файла

Добавляемые числа — десятичные 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 эти правила называются стандартом вызова процедур или PCS. Это соглашения между двумя или тремя сторонами. PCS определяет следующее:

  • Какие регистры µP используются для передачи аргументов в функцию (подпрограмму)
  • Какие регистры µP используются для возврата результата функции, выполняющей вызов, которая называется вызывающей стороной?
  • Какой микропроцессор регистрирует вызываемую функцию, известную как вызываемая, может повредить
  • Какие регистры µP вызываемый абонент не может повредить

6.49 Прерывания
Для процессора ARM доступны два типа схем контроллера прерываний:

  • Стандартный контроллер прерываний: обработчик прерываний определяет, какое устройство требует обслуживания, считывая регистр битовой карты устройства в контроллере прерываний.
  • Контроллер векторных прерываний (VIC): определяет приоритет прерываний и упрощает определение того, какое устройство вызвало прерывание. После связывания приоритета и адреса обработчика с каждым прерыванием VIC подает сигнал прерывания процессору только в том случае, если приоритет нового прерывания выше, чем приоритет выполняющегося в данный момент обработчика прерывания.

Примечание : Исключение относится к ошибке. Подробности векторного контроллера прерываний для 32-битного компьютера ARM следующие (64-битный аналогичный):

Таблица 6.49.1
Векторное исключение/прерывание ARM для 32-битного компьютера
Исключение/Прерывание Короткая рука Адрес Высокий адрес
Перезагрузить ПЕРЕЗАГРУЗИТЬ 0x00000000 0xffff0000
Неопределенная инструкция ФДООН 0x00000004 0xffff0004
Программное прерывание SWI 0x00000008 0xffff0008
Прерывание предварительной выборки пабт 0x0000000C 0xffff000C
Дата аборта ДАБТ 0x00000010 0xffff0010
Сдержанный 0x00000014 0xffff0014
Запрос прерывания прерывание 0x00000018 0xffff0018
Запрос быстрого прерывания FIQ 0x0000001C 0xffff001C

Это похоже на схему архитектуры 6502, где НМИ , БР , и прерывание могут иметь указатели на нулевой странице, а соответствующие процедуры находятся в верхней части памяти (ОС ПЗУ). Краткое описание строк предыдущей таблицы следующее:

ПЕРЕЗАГРУЗИТЬ
Это происходит при включении процессора. Он инициализирует систему и настраивает стеки для разных режимов процессора. Это исключение с наивысшим приоритетом. При входе в обработчик сброса CPSR находится в режиме SVC, а биты IRQ и FIQ устанавливаются в 1, маскируя любые прерывания.

ДАТА АБОРТА
Второй по значимости приоритет. Это происходит, когда мы пытаемся прочитать/записать неверный адрес или получить неправильный доступ. При входе в обработчик прерывания данных IRQ будут отключены (I-бит установлен в 1), а FIQ будет включен. IRQ маскируются, но FIQ остаются незамаскированными.

FIQ
Прерывания с наивысшим приоритетом, IRQ и FIQ, отключаются до тех пор, пока не будет обработан FIQ.

прерывание
Прерывание с высоким приоритетом, обработчик IRQ, вводится только в том случае, если нет текущего FIQ и прерывания передачи данных.

Прерывание предварительной выборки
Это похоже на прерывание данных, но происходит при сбое получения адреса. При входе в обработчик IRQ отключаются, но FIQ остаются включенными и могут произойти во время прерывания предварительной выборки.

SWI
Исключение программного прерывания (SWI) возникает, когда инструкция SWI выполняется, и ни одно из других исключений с более высоким приоритетом не было отмечено.

Неопределенная инструкция
Исключение «Неопределенная инструкция» возникает, когда инструкция, не входящая в набор команд ARM или Thumb, достигает стадии выполнения конвейера, и ни одно из других исключений не было отмечено. Это тот же приоритет, что и SWI, поскольку все может происходить одновременно. Это означает, что выполняемая инструкция не может одновременно быть инструкцией SWI и неопределенной инструкцией.

Обработка исключений ARM
При возникновении исключения происходят следующие события:

  • Сохраните CPSR в SPSR режима исключений.
  • ПК сохраняется в LR режима исключений.
  • Регистру связи присваивается определенный адрес на основе текущей инструкции. Например: для ISR LR = последняя выполненная инструкция + 8.
  • Обновите CPSR об исключении.
  • Установите ПК на адрес обработчика исключений.

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

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

Программу следует писать сначала с инструкциями, а затем с данными (множественное число от слова data — данные). Расстояние между инструкциями и данными может составлять всего несколько байт. Для программы и инструкции, и данные могут находиться в одной или двух отдельных секциях памяти.

6.6 Гарвардская архитектура

Один из первых компьютеров называется Harvard Mark I (1944 г.). Строгая гарвардская архитектура использует одно адресное пространство для программных инструкций и другое отдельное адресное пространство для данных. Это означает, что есть два отдельных воспоминания. Ниже представлена ​​архитектура:


Рисунок 6.71 Гарвардская архитектура

Блок управления выполняет декодирование команд. Арифметико-логическое устройство (АЛУ) выполняет арифметические операции с помощью комбинационной логики (вентилей). АЛУ также выполняет логические операции (например, сдвиг).

В микропроцессоре 6502 инструкция сначала поступает в микропроцессор (блок управления), а затем данные (единственное число для данных) передаются в регистр µP, прежде чем они взаимодействуют. Для этого требуется как минимум два тактовых импульса, и это не одновременный доступ к инструкции и данным. С другой стороны, гарвардская архитектура обеспечивает одновременный доступ к инструкциям и данным, при этом и инструкция, и данные поступают в микропроцессор одновременно (код операции в блок управления и данные в регистр микропроцессора), экономя по крайней мере один тактовый импульс. Это форма параллелизма. Эта форма параллелизма используется в аппаратном кэше современных материнских плат (см. следующее обсуждение).

6.7 Кэш-память

Кэш-память (ОЗУ) — это высокоскоростная область памяти (по сравнению со скоростью основной памяти), в которой временно хранятся инструкции программы или данные для будущего использования. Кэш-память работает быстрее основной памяти. Обычно эти инструкции или элементы данных извлекаются из последней оперативной памяти и, вероятно, вскоре потребуются снова. Основная цель кэш-памяти — увеличить скорость многократного доступа к одним и тем же ячейкам основной памяти. Чтобы быть эффективным, доступ к кэшированным элементам должен быть значительно быстрее, чем доступ к исходному источнику инструкций или данных, который называется резервным хранилищем.

При использовании кэширования каждая попытка доступа к ячейке основной памяти начинается с поиска в кэше. Если запрошенный элемент присутствует, процессор немедленно извлекает и использует его. Это называется попаданием в кэш. Если поиск в кэше не удался (промах в кэше), инструкция или элемент данных должны быть извлечены из резервного хранилища (основной памяти). В процессе получения запрошенного элемента копия добавляется в кэш для предполагаемого использования в ближайшем будущем.

Блок управления памятью
Блок управления памятью (MMU) — это схема, которая управляет основной памятью и соответствующими регистрами памяти на материнской плате. Раньше это была отдельная интегральная схема на материнской плате; но сегодня это обычно часть микропроцессора. MMU также должен управлять кэшем (схемой), который сегодня также является частью микропроцессора. Схема кэша в прошлом представляла собой отдельную интегральную схему.

Статическая оперативная память
Статическое ОЗУ (SRAM) имеет значительно более быстрое время доступа, чем DRAM, хотя и за счет значительно более сложной схемы. Битовые ячейки SRAM занимают гораздо больше места на кристалле интегральной схемы, чем ячейки устройства DRAM, способного хранить эквивалентное количество данных. Основная память (ОЗУ) обычно состоит из DRAM (динамического ОЗУ).

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

Как правило, области кэш-памяти малы (по количеству байтов) по сравнению с резервным хранилищем (основной памятью). Устройства кэш-памяти рассчитаны на максимальную скорость, что обычно означает, что они более сложны и дороги в пересчете на бит, чем технология хранения данных, используемая в резервном хранилище. Из-за ограниченного размера устройства кэш-памяти имеют тенденцию быстро заполняться. Если в кэше нет доступного места для хранения новой записи, старую запись необходимо удалить. Контроллер кэша использует политику замены кэша, чтобы выбрать, какая запись кэша будет перезаписана новой записью.

Целью кэш-памяти микропроцессора является максимизация процента попаданий в кэш с течением времени, обеспечивая тем самым наивысшую устойчивую скорость выполнения инструкций. Для достижения этой цели логика кэширования должна определить, какие инструкции и данные будут помещены в кэш и сохранены для использования в ближайшем будущем.

Логика кэширования процессора не гарантирует, что элемент кэшированных данных когда-либо будет использован снова после того, как он будет вставлен в кэш.

Логика кэширования основана на вероятности того, что из-за временной (повторяющейся во времени) и пространственной (пространственной) локальности существует очень большая вероятность того, что к кэшированным данным будет осуществлен доступ в ближайшем будущем. В практических реализациях на современных процессорах попадания в кэш обычно происходят при 95–97 процентах обращений к памяти. Поскольку задержка кэш-памяти составляет небольшую часть задержки DRAM, высокая частота попаданий в кэш приводит к существенному повышению производительности по сравнению с схемой без кэша.

Некоторый параллелизм с кэшем
Как упоминалось ранее, в хорошей программе в памяти инструкции отделены от данных. В некоторых системах кэш-памяти имеется схема кэш-памяти «слева» от процессора, а другая схема кэш-памяти находится «справа» от процессора. Левый кеш обрабатывает инструкции программы (или приложения), а правый кеш обрабатывает данные той же программы (или того же приложения). Это приводит к лучшему увеличению скорости.

6.8 Процессы и потоки

Компьютеры CISC и RISC имеют процессы. Процесс находится в программном обеспечении. Программа, которая выполняется (выполняется), представляет собой процесс. Операционная система поставляется со своими собственными программами. Во время работы компьютера также выполняются программы операционной системы, обеспечивающие работу компьютера. Это процессы операционной системы. Пользователь или программист может писать свои собственные программы. Когда программа пользователя запущена, это процесс. Не имеет значения, написана ли программа на языке ассемблера или на языке высокого уровня, таком как C или C++. Все процессы (пользовательские или ОС) управляются другим процессом, называемым «планировщиком».

Поток похож на подпроцесс, принадлежащий процессу. Процесс может запуститься и разделиться на потоки, а затем продолжиться как один процесс. Процесс без потоков можно рассматривать как основной поток. Процессы и их потоки управляются одним и тем же планировщиком. Планировщик сам по себе является программой, когда он находится на диске ОС. При работе в памяти планировщик представляет собой процесс.

6.9 Многопроцессорность

Потоки управляются почти как процессы. Многопроцессорность означает одновременное выполнение нескольких процессов. Есть компьютеры только с одним микропроцессором. Существуют компьютеры с более чем одним микропроцессором. При использовании одного микропроцессора процессы и/или потоки используют один и тот же микропроцессор в режиме чередования (или разделения времени). Это означает, что процесс использует процессор и останавливается, не завершив свою работу. Другой процесс или поток использует процессор и останавливается, не завершив свою работу. Затем другой процесс или поток использует микропроцессор и останавливается, не завершив свою работу. Это продолжается до тех пор, пока все процессы и потоки, поставленные планировщиком в очередь, не получат долю процессора. Это называется параллельной многопроцессорной обработкой.

Когда имеется более одного микропроцессора, происходит параллельная многопроцессорная обработка, а не параллелизм. В этом случае каждый процессор запускает определенный процесс или поток, отличный от того, который выполняет другой процессор. Все процессоры на одной материнской плате одновременно запускают разные процессы и/или разные потоки в параллельной многопроцессорной обработке. Процессы и потоки в параллельной многопроцессорной обработке по-прежнему управляются планировщиком. Параллельная многопроцессорная обработка выполняется быстрее, чем параллельная многопроцессорная обработка.

На этом этапе читатель может задаться вопросом, насколько параллельная обработка выполняется быстрее, чем параллельная обработка. Это связано с тем, что процессоры совместно используют (должны использовать в разное время) одну и ту же память и порты ввода/вывода. Ну а с использованием кэша общая работа материнской платы происходит быстрее.

6.10 Пейджинг

Блок управления памятью (MMU) — это схема, расположенная рядом с микропроцессором или в микропроцессорной микросхеме. Он обрабатывает карту памяти или подкачку и другие проблемы с памятью. Ни 6502 µP, ни компьютер Commodore-64 не имеют MMU как такового (хотя в Commodore-64 все еще есть некоторое управление памятью). Commodore-64 обрабатывает память путем подкачки, где каждая страница равна 256. 10 длина байт (100 16 байтов). Ему не обязательно было обрабатывать память путем подкачки. У него все еще может быть просто карта памяти, а затем программы, которые просто вписываются в разные назначенные им области. Ну, подкачка — это один из способов обеспечить эффективное использование памяти без большого количества разделов памяти, в которых не могут быть данные или программы.

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

Таблица 6.10.1
Физически адресуемые страницы для архитектуры x86
База 16 адресов Страницы База 10 адресов
ФФФФ000 – ФФФФФФФ Страница 1 048 575 4 294 963 200 – 4 294 967 295
ФФФФЕ000 – ФФФФФФ Страница 1 044 479 4 294 959 104 – 4 294 963 199
ФФФФД000 – ФФФФДФФ Страница 1 040 383 4 294 955 008 – 4 294 959 103
|
|
|
|
|
|
|
|
|
00002000 – 00002FFF Страница 2 8 192 – 12 288
00001000 – 00001FFF Страница 1 4096 – 8191
00000000 – 00000FFF Страница 0 0 – 4095

Сегодня приложение состоит из более чем одной программы. Одна программа может занимать меньше страницы (менее 4096) или две и более страниц. Таким образом, приложение может занимать одну или несколько страниц, каждая из которых имеет длину 4096 байт. Разные люди могут написать приложение, при этом каждому будет назначена одна или несколько страниц.

Обратите внимание, что страница 0 имеет номера от 00000000H до 00000FFF.
страница 1 — от 00001000H до 00001FFFH, страница 2 — от 00002000 ЧАС – 00002FFF ЧАС , и так далее. В 32-битном компьютере в процессоре имеется два 32-битных регистра для физической адресации страниц: один для базового адреса, другой для индексного адреса. Например, для доступа к байтам страницы 2 регистр базового адреса должен быть 00002. ЧАС это первые 20 бит (слева) начальных адресов страницы 2. Остальные биты в диапазоне 000. ЧАС в ФФФ ЧАС находятся в регистре, называемом «индексным регистром». Таким образом, ко всем байтам страницы можно получить доступ, просто увеличив содержимое индексного регистра с 000. ЧАС в ФФФ ЧАС . Содержимое индексного регистра добавляется к содержимому, которое не изменяется в базовом регистре, для получения эффективного адреса. Эта схема адресации индекса справедлива и для других страниц.

Однако на самом деле программа на языке ассемблера пишется для каждой страницы не так. Для каждой страницы программист пишет код, начиная со страницы 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-компьютера в битовом выражении: байт, полуслово, слово и двойное слово.
в) Да или нет. Означают ли двойное и четверное слово одно и то же в архитектурах CISC и RISC?

3 а) Для x64 количество байтов для инструкций языка ассемблера варьируется от чего до чего?
б) Фиксировано ли количество байтов для всех инструкций языка ассемблера для ARM 64? Если да, то каково количество байтов для всех инструкций?

4) Перечислите наиболее часто используемые инструкции языка ассемблера для x64 и их значения.

5) Перечислите наиболее часто используемые инструкции языка ассемблера для ARM 64 и их значения.

6) Нарисуйте маркированную блок-схему старого компьютера Гарвардской архитектуры. Объясните, как его инструкции и данные используются в кэше современных компьютеров.

7) Различайте процесс и поток и дайте имя процессу, который обрабатывает процессы и потоки в большинстве компьютерных систем.

8) Кратко объясните, что такое многопроцессорность.

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