По сути, каждый современный компьютер - это немного напористая машина. Обычно он разбрасывает биты в кластерах данных, называемых байтами, словами, словами или словами.
Байт состоит из 8 битов, слова 2 байта (или 16 битов), слова 2 слова (или 32 бита) и слова 2 слова (или 64 бита). Это не единственный способ расставить биты. 128-битные и 256-битные манипуляции также происходят, часто в инструкциях SIMD.
Инструкции по сборке работают с регистрами, а адреса памяти обычно работают в одной из вышеуказанных форм.
ALU (арифметико-логические единицы) работают с такими блоками битов, как если бы они представляли целые числа (обычно формат дополнения Two), а FPU - как со значениями с плавающей запятой (обычно в стиле IEEE 754 float
и double
). Другие части будут действовать так, как если бы они были связаны данными некоторого формата, символов, записей таблицы, инструкций процессора или адресов.
На типичном 64-битном компьютере пакеты по 8 байт (64 бита) являются адресами. Мы отображаем эти адреса условно в шестнадцатеричном формате (например 0xabcd1234cdef5678
), но для людей это простой способ чтения битовых комбинаций. Каждый байт (8 бит) записывается в виде двух шестнадцатеричных символов (эквивалентно, каждый шестнадцатеричный символ - от 0 до F - представляет 4 бита).
Что на самом деле происходит (для некоторого уровня на самом деле), так это то, что есть биты, которые обычно хранятся в регистре или хранятся в соседних местах в банке памяти, и мы просто пытаемся описать их другому человеку.
Следующий указатель состоит из запроса контроллера памяти предоставить нам некоторые данные в этом месте. Как правило, вы запрашиваете у контроллера памяти определенное количество байтов в определенном месте (ну, неявно, диапазон ячеек, обычно смежных), и оно доставляется через различные механизмы, в которые я не пойду.
Код обычно указывает место назначения для данных, которые будут извлечены - регистр, другой адрес памяти и т. Д. - и обычно плохая идея загружать данные с плавающей запятой в регистр, ожидающий целое число, или наоборот.
Тип данных в C / C ++ - это то, что компилятор отслеживает, и это меняет то, какой код генерируется. Обычно в данных нет ничего, что делало бы их фактически одного типа. Просто набор битов (сгруппированных в байты), которыми код манипулирует целочисленным образом (или плавающим, или адресным способом).
Есть исключения из этого. Есть архитектуры , где определенные вещи , которые другой вид бит. Наиболее распространенным примером являются защищенные страницы выполнения - хотя инструкции, указывающие процессору, что это биты, во время выполнения страницы (памяти), содержащие код для выполнения, помечаются специально, не могут быть изменены, и вы не можете выполнять страницы, которые не отмечены как страницы исполнения.
Есть также данные только для чтения (иногда хранящиеся в ПЗУ, которые физически не могут быть записаны в!), Проблемы с выравниванием (некоторые процессоры не могут загрузить double
s из памяти, если они не выровнены определенным образом, или инструкции SIMD, требующие определенного выравнивания), и множество другие особенности архитектуры
Даже вышеупомянутый уровень детализации является ложью. Компьютеры "не" толкаются вокруг битов, они действительно толкают напряжение и ток. Эти напряжения и ток иногда не делают того, что они «должны» делать на уровне абстракции битов. Микросхемы предназначены для обнаружения большинства таких ошибок и их исправления, при этом абстракция более высокого уровня не должна знать об этом.
Даже это ложь.
Каждый уровень абстракции скрывает нижеприведенный уровень и позволяет вам думать о решении проблем без необходимости учитывать диаграммы Фейнмана для распечатки "Hello World"
.
Таким образом, на достаточном уровне честности компьютеры выдвигают биты, и эти биты получают значение в зависимости от того, как они используются.