С тех пор как я начал интересоваться, как работают вещи на моем компьютере, у меня появилась мечта написать собственную операционную систему с нуля. И вот чему я научился за последние 8 месяцев:
Введение
Для начала вам нужно знать, как работает компьютер на низком уровне, чтобы понять, что вы делаете, поэтому давайте начнем с самого основного:
Транзистор
Транзистор — это электронный компонент, который действует как переключатель, он использует полупроводники (чаще всего кремний) для включения или выключения электрических цепей. Мы можем использовать их для создания так называемых логических ворот.
Обычный транзистор имеет три конца: коллектор, базу и эмиттер. Каждый из них делает то, что описывает его название, но я все равно объясню.
Коллектор: Это вывод, который собирает напряжение от источника электричества схемы, он должен быть всегда включен.
База: Этот вывод собирает входное напряжение, которое может быть либо включено, либо выключено, оно не обязательно должно быть таким же, как на коллекторе, но оно должно поступать из той же цепи, иначе они не будут соединены, и электроны не будут иметь пути для движения в цепи. (tl;dr: база и коллектор должны иметь общую землю).
Эмиттер: Этот вывод выдает напряжение, если на входе базы высокий уровень (включено).
Теперь, когда вы знаете основы работы транзисторов, мы переходим к изучению того, что представляют собой эти волшебные (и сложные) логические ворота.
Логические затворы
Логические вентили — это практически электронная схема предложений, которые вы изучали на уроках философии, но я собираюсь объяснить их основы.
Как мы узнали ранее, компьютеры работают по принципу условий, благодаря природе транзисторов, присутствующих в процессоре, и поэтому нам нужно знать больше об этих условиях.
С помощью сложной серии схем можно заставить транзистор «думать» логически, используя эти логические затворы:
Not: Это эквивалент отрицания в философии, он инвертирует вход, поэтому, например, если вы вводите HIGH в этот логический гейт, выход будет LOW (выключен).
Или: Эти логические ворота принимают два (или больше, как и все ворота, которые мы будем изучать с этого момента) входа, и их выход будет ВЫСОКИМ, только если один или несколько входов будут ВЫСОКИМИ.
И: Выход этого логического гейта будет ВЫСОКИМ только в том случае, если все его входы будут ВЫСОКИМИ.
Xor: Выход этого логического гейта будет ВЫСОКИМ только в том случае, если его входы отличаются друг от друга. И теперь, когда мы изучаем эту концепцию, вы должны знать, что логические ворота могут принимать только два входа одновременно, поэтому, когда входов больше двух, их нужно объединить. Так, xor с тремя входами будет ((p ⊻ q) ⊻ r)
.
Нор: Этот логический гейт представляет собой соединение гейтов not
и or
, что означает, что выход будет таким, как если бы вы пропустили гейт NOT через условие OR (каждый возможный вход возвращает НИЗКИЙ уровень, кроме того, где все значения НИЗКИЕ).
Теперь с этими знаниями мы можем перейти к процессору.
ЦЕНТРАЛЬНЫЙ ПРОЦЕССОР
Центральный процессор (он же CPU, или просто процессор) — это схема, которая обрабатывает все сигналы в вашем компьютере. Обычно он делится на несколько блоков, таких как ALU (блок арифметической обработки) и ядра (их можно представить как крошечные процессоры, на которые делятся задания).
В каждом из этих небольших блоков используются логические затворы и транзисторы, и да, вы можете производить математические вычисления, используя «Да» и «Нет».
У процессора также есть набор инструкций, которые мы будем использовать для программирования того, что он делает во время выполнения нашего кода, как вы узнаете позже, они общего назначения и очень интуитивно понятны.
В процессоре также есть встроенные участки памяти (в которых хранятся данные), называемые регистрами, в архитектуре x86 (та, на которой работает большинство ПК) есть регистры общего назначения, но есть и такие, которые предназначены для конкретных случаев использования, например, для хранения данных, видео и т.д.
С этим перейдем к памяти.
Память
Память (не путать с памятью) — это компонент компьютера, используемый для загрузки программ, которые вы запускаете на компьютере. Информация, которую необходимо хранить программе, временно загружается в память компьютера. Этот компонент также известен как RAM (память с произвольным доступом), и он является летучим, то есть его содержимое стирается при выключении питания.
Память делится на адреса — крошечные участки, которые могут содержать данные. Они обычно представляются в шестнадцатеричной системе счисления, которая начинается с «0x», как и «0b» в двоичной системе.
Теперь давайте перейдем к некоторым действиям.
Язык ассемблера
Ассемблер — это низкоуровневый язык программирования общего назначения, предназначенный для прямого взаимодействия с аппаратным обеспечением компьютера (в основном с процессором и памятью). Он довольно прост по сравнению с написанием двоичных кодов вручную. Ассемблер использует инструкции процессора и должен быть скомпилирован («собран») для выполнения.
Hello World!
Поскольку этот пост становится все больше и больше, не доходя до кода, я собираюсь закончить его кодом для сообщения «Hello world» на экране, написанным на ассемблере, но не волнуйтесь, я объясню, как это работает.
org 0x7C00
bits 16
xor ax, ax
mov ds, ax
start:
mov si, msg
mov ah, 0x0E
.loop lodsb
or al, al
jz halt
int 0x10
jmp .loop
halt: hlt
msg: db "Hello world!", 0
times 510 - ($ - $$) db 0
dw 0xAA55
Первая строка определяет местоположение программы в памяти, 0x7c00
— это первое значение адреса, в котором будет храниться программа. Есть причина, почему это число, которую я объясню в другом сообщении.
bits 16
определяет, что программа будет работать на 16 битах (хотя наш процессор может быть 32 или 64 бита. Это соглашение архитектуры x86).
xor ax, ax
означает, что следующая строка будет запущена, если условие истинно. Она сравнивает регистр ax
с самим собой (опять же, для этого есть причина, которую я объясню позже).
mov ds, ax
перемещает содержимое ax
в ds
, оба регистра процессора.
start:
, .loop
, halt:
и msg:
(см. далее) определяют участки кода (можно считать их функциями), хотя участок msg:
больше похож на переменную, поскольку сразу возвращает «Hello world» и нулевой символ завершения.
mov si, msg
перемещает содержимое переменной msg
в регистр si
. Позже это будет использовано для отображения значения msg.
Секция .loop
— это рекурсивная функция, которая вызывает себя снова и снова, пока символ оценки не станет нулевым символом завершения (