#heading[ISA.]
#emph[ISA (Архитектура фон Неймана и ее альтернативы. Что описывает ISA? Assembler MIPS).]

#import "/commons.typ": imagebox

== Архитектура фон Неймана
#emph[Архитектура фон Неймана (a.k.a. Принстонская архитектура)] — широко известный принцип совместного хранения команд и данных в памяти компьютера. В общем случае, когда говорят об архитектуре фон Неймана, подразумевают принцип хранения данных и инструкций в одной памяти, но вообще она включает в себя пять базисных принципов устройства ЭВМ:

=== Использование двоичной системы счисления
ЭВМ, реализующая архитектуру фон Неймана должна использовать двоичную систему счисления.

_Альтернативы:_
#columns(2)[
  #imagebox("difference_engine.jpg", height: 140pt, label: [
    _Аналитическая машина Бэббиджа_ --- первая в мире программируемая вычислительная машина, работает на основе десятичной системы счисления.
  ]) 
  #colbreak()
  #imagebox("soviet_setun.jpg", height: 140pt, label: [
    _Советская «Сетунь»_ — единственная в мире ЭВМ на основе троичного кода.
  ]) 
]

=== Принцип адресности памяти
Структурно основная память состоит из пронумерованных ячеек, причём процессору в произвольный момент доступна любая ячейка. Двоичные коды команд и данных разделяются и хранятся в ячейках памяти, а для доступа к ним используются номера соответствующих ячеек — адреса.

_Альтернативы:_
#columns(2)[
  #imagebox("jvm_stack_and_heap.png", label: [
    Стековая архитектура\
    («Сетунь», JVM) 
  ])
  #colbreak()
  #imagebox("turing_machine.jpeg", label: [
    Ленточная архитектура\
    (машина Алана Тьюринга)
  ])
]
#pagebreak()

=== Однородность памяти
Код и данные хранятся в одной и той же памяти.

_Альтернативы:_
#imagebox("harvard_architecture.png", height: 150pt, label: [
  Гарвардская архитектура\
  (память данных и команд раздельна)
])
#columns(2)[
  #align(center)[#strong[Архитектура фон Неймана]]

  #align(center)[_Плюсы_]
  - Можно эффективно использовать всю имеющуюся память.
  - Проще контроллер.
  - Одна шина.
  #align(center)[_Минусы_]
  - Так как инструкции хранятся в памяти, их можно случайно испортить во время выполнения программы.
  #align(center)[_Непонятно_]
  - Однородный доступ к коду и данным.
  #colbreak()
  
  
  #align(center)[#strong[Гарвардская архитектура]]
  #align(center)[_Плюсы_]
  - Можно одновременно читать и код, и данные.
  - Если сделать память кода read-only, то вполне безопасно.
  #align(center)[_Минусы_]
  - Усложняется контроллер памяти.
  - В 2 раза больше шин.
  - Память может "простаивать без дела". Наример, если программа маленькая.
  #align(center)[_Непонятно_]
  - Для данных и инструкций можно использовать память с разными характеристиками.
]

=== Принцип программного управления
ЭВМ выполняет программы, записанные в памяти. Альтернативой были попытки "зашить" программу прямо в железо, но, очевидно, такой подход обречён, так как он предлагает гораздо более маленькую вариативность кода: под конкретную программу нужно собирать свою железку.

=== Принцип последовательного выполнения команд
Казалось бы, понятный принцип, который соблюдается в современных компьютерах: команды выполняются последовательно, одна за другой. Но с появлением многоядерных процессоров возникло многопоточное программирование. Так что, фактически, каждый компьютер, в котором установлен многоядерный процессор, нарушает данный принцип.

== ISA (Instruction Set Architecture)
#emph[ISA] --- это абстрактная модель компьютера. Как правило, #emph[ISA] определяет архитектуру памяти, разрядность адресов, режими адресации, количество регистров, наборы команд машинного языка и их кодирование, типы данных, обработку исключений, etc.

Примеры #emph[ISA]:
- x86
- ARM
- RISC-V
- MIPS
#pagebreak()

=== Огранизация памяти и взаимодействие с памятью
#columns(2)[
  #align(center)[*Стековая*]
  - Операнды лежат на стеке
  - Операция берёт два значения с верхушки стека и возвращает одно
  
  #align(center)[*Reg-Reg*]
  - Операнды в регистрах, результат помещается в регистр
  
  #align(center)[*Reg-Mem*]
  - Один из операндов может быть из памяти
  #colbreak()
  
  #align(center)[*Аккумуляторная*]
  - Стек размера 1
  - Один операнд из аккумулятора, второй из памяти. Результат помещается в аккумулятор
  
  #align(center)[*Mem-Mem*]
  - Оба операнда могут быть из памяти
]

=== Кодирование команд
#columns(2)[
  #align(center)[*Команды переменной длины*]
  - Команды имеют разную длину
  - Частоиспользуемые команды могут кодироваться меньшим количеством байт, что хорошо
  - Сложно декодировать
  #emph[ISA x86]: команды имеют длину 1-15 байт
  #colbreak()
  #align(center)[*Команды постоянный длины*]
  
  - Команды имеют постоянную длину
  - Иногда приходится разбивать одну команду на две из-за нехватки бит для сложных команд
  - Просто декодировать
  В #emph[MIPS] все команды по 4 байта
]

=== Наборы команд
#columns(2)[
  #align(center)[*CISC - complex instruction set computer*]
  - Акцент за железо
  - Минимизируется количество инструкций в програиме
  - Инструкции могут выполнятся несколько тактов процессора
  - Сложнее реализация железа
  #colbreak()
  
  #align(center)[*RISC - reduced instruction set computer*]
  - Акцент за программы
  - Сложные команды реализуются программно через простые
  - Все инструкции выполняются за один такт
  - Проще реализация железа
]

Архитектура x86 предоставляет программисту интерфейс CISC, но под капотом интерпритирует команды в простейшие RISC инструкции.

=== Режимы адресации
- Register: add r1 r2 r3, _(r1 = r2 + r3)_
- Immediate: add r1 r2 5, _(r1 = r2 + 5)_
- Register inderect: add r1 r2 (r3), _(r1 = r2 + mem\[r3\])_
- Displacement: add r1 r2 100(r3), _(r1 = r2 + mem\[100+r3\])_
- Absolute: add r1 r2 0xabcd, _(r1 = r2 + mem\[0xabcd\])_ 
#pagebreak()

== Assembler MIPS
=== Регистры
#imagebox("mips_registers.png", height: 200pt)

=== Типы команд
#columns(3)[
  #imagebox("mips_r-type.png", width: 170pt, label: [  
    op - код операции\
    rs, rt - регистры операндов\
    rd - регистр для результата\
    shamt - для побитового сдвига\
    funct - доп. код операции\
  ])
  #colbreak()
  #imagebox("mips_i-type.png", width: 170pt, label: [
    op - код операции\
    rs - регистр операнда\
    rt - регистр для результата\
    imm - 16-и битная константа
  ])
  #colbreak()
  #imagebox("mips_j-type.png", width: 170pt, label: [
    op - код операции\
    addr - адрес, с которого произойдет дальшейшее исполнение инструкций
  ])
  #colbreak()
]


