Большая часть содержания этого ответа изначально пришла из этот ответ (написанный до этого другой вопрос был помечен как дубликат). Поэтому я обсуждаю использование 8-битных значений (хотя этот вопрос касался 32-битных значений), но это нормально, потому что 8-битные значения проще понять концептуально, и те же самые понятия применимы к большим значениям, например, 32-битной арифметике.
Когда вы добавляете два числа, которые являются 8-битными, наибольшее число, которое вы можете получить (0xFF + 0xFF = 1FE). На самом деле, если вы умножите два числа, которые являются 8-битными, наибольшее число, которое вы можете получить (0xFF * 0xFF = 0xFE01), все равно будет 16-битным, дважды 8-битным.
Теперь, вы можете предположить, что x-битный процессор может отслеживать только x-битные значения. (Например, 8-битный процессор может отслеживать только 8 бит.) Это неточно. 8-битный процессор получает данные в 8-битных кусочках (Эти “кусочки” обычно имеют формальный термин: “слово”. На 8-ми битном процессоре используются 8-битные слова. На 64-битном процессоре могут использоваться 64-битные слова.)
Таким образом, когда вы даете компьютеру 3 байта:
Байт #1: Инструкция MUL
Байт #2: байты старшего порядка (например, 0xA5)
Байт #3: байты нижнего порядка (например, 0xCB)
Компьютер может сгенерировать результат, превышающий 8 бит. ЦП может выдавать такие результаты:
0100 0000 0100 0010 xxxxx xxxx xxxx xxxx 1101 0111
a.k.a.:
0x4082xxxxD7
Теперь, позвольте мне интерпретировать это для вас:
0x просто означает, что следующие цифры являются шестнадцатеричными.
я рассмотрю “40” более подробно.
82 - это часть регистра “A”, который представляет собой серию из 8 бит.
xx и xx - это часть двух других регистров, названных регистром “B” и регистром “C”. Причина, по которой я не заполнил эти биты нулями или единицами, заключается в том, что команда “ADD” (посылаемая в CPU) может привести к тому, что эти биты останутся неизменными командой (в то время как большинство других битов, которые я использую в этом примере, могут быть изменены, за исключением некоторых флаговых битов).
D7 поместится в большее количество бит, называемых регистром “D”.
Регистр “A” - это всего лишь часть памяти. Регистры встроены в процессоры, так что процессор может обращаться к регистрам без необходимости взаимодействия с памятью на карте памяти.
Так что математический результат 0xA5 умноженный на 0xCB равен 0x82D7.
Теперь, почему биты разделились на регистры A и D, а не на регистры A и B, или на регистры C и D? Ну, опять же, это пример сценария, который я использую, имея в виду довольно схожий по концепции с реальным языком ассемблера (Intel x86 16-битный, используемый в Intel 8080 и 8088 и многими более новыми процессорами). Могут быть некоторые общие правила, такие как регистр “C”, обычно используемый в качестве индекса для подсчета операций (типичный для циклов), и регистр “B”, используемый для отслеживания смещений, которые помогают указывать места в памяти. Таким образом, “A” и “D” могут быть более распространены для некоторых общих арифметических функций.
Каждая инструкция для CPU должна иметь некоторую документацию, используемую людьми, которые программируют на Ассемблере. Эта документация должна указывать, какие регистры используются каждой командой. (Так что выбор, какие регистры использовать, часто задается проектировщиками ЦП, а не программистами языка Ассемблера. Хотя, может быть некоторая гибкость.)
Сейчас, возвращаясь к “40” в приведённом выше примере: это серия бит, часто называемая “регистром флагов”. Каждый бит в регистре флагов имеет имя. Например, есть “переполнение” бита, которое может быть установлено процессором, если полученный результат больше пространства, которое может хранить один байт результата. (К биту “переполнения” часто можно отнести сокращенное имя “OF”. Это заглавное “о”, а не “ноль”). Программное обеспечение может проверить значение этого флага и заметить “проблему”. Работа с этим битом часто невидимо обрабатывается языками более высокого уровня, поэтому начинающие программисты часто не знают, как взаимодействовать с флагами процессора. Тем не менее, программисты, занимающиеся ассемблировкой, могут часто обращаться к некоторым из этих флагов так же, как и к другим переменным.
Например, у вас может быть несколько инструкций ADD. Одна команда ADD может хранить 16 бит результатов в регистре A и регистре D, в то время как другая команда может просто хранить 8 младших битов в регистре A, игнорировать регистр D и указывать бит переполнения. Затем, позже (после хранения результатов регистра A в оперативной памяти), вы можете использовать другую инструкцию ADD, которая хранит только 8 младших битов в регистре (возможно, в регистре A.) Необходимость использования флага переполнения может зависеть от того, какую инструкцию по умножению вы используете.
(Также часто встречается флаг “переполнения”, на случай, если вы вычитаете слишком много, чтобы вписаться в желаемый результат)
Просто чтобы показать вам, как все запуталось:
Intel 4004 был 4-битным процессором
Intel 8008 был 8-битным процессором. Он имел 8-битные регистры A, B, C и D.
Intel 8086 был 16-битным процессором. Он имел 16-битные регистры с именами AX, BX, CX и DX.
Intel 80386 представлял собой 32-битный процессор. Он имел 32-битные регистры EAX, EBX, ECX и EDX.
Процессоры Intel x64 имеют 64-битные регистры RAX, RBX, RCX и RDX. Микросхемы x64 могут выполнять 16-битный код (в некоторых режимах работы), а также интерпретировать 16-битные инструкции. При этом биты, составляющие регистр AX, составляют половину битов, составляющих регистр EAX, а это половина битов, составляющих регистр RAX. Поэтому при изменении значения AX также меняются EAX и RAX, поскольку те биты, которые используются AX, являются частью битов, используемых RAX. (Если вы изменяете EAX на значение, кратное 65 536, то младшие 16 битов остаются неизменными, поэтому AX не изменяется. Если изменить EAX на значение, не кратное 65 536, то это повлияет и на AX.)
Есть больше флагов и регистров, чем только те, о которых я упоминал. Для простого концептуального примера я выбрал несколько общеупотребительных.
Теперь, если вы работаете на 8-битном процессоре, то при записи в память вы можете обнаружить некоторые ограничения на возможность обращения к 8-битному адресу, а не к 4-битному или 16-битному. Детали будут варьироваться в зависимости от процессора, но если у Вас есть такие ограничения, то процессор может иметь дело с 8-битными словами, поэтому процессор чаще всего называют “8-битным процессором”.