Большая часть содержания этого ответа изначально была получена из этого ответа (написанного до того, как другой вопрос был помечен как дубликат). Поэтому я обсуждаю использование 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 хххх хххх хххх хххх 1101 0111
иначе:
0x4082xxxxD7
Теперь позвольте мне истолковать это для вас:
0x означает, что следующие цифры шестнадцатеричные.
Я кратко расскажу о "40".
82 является частью регистра "А", который представляет собой последовательность из 8 битов.
xx и xx являются частью двух других регистров, называемых регистром "B" и регистром "C". Причина, по которой я не заполнил эти биты нулями или единицами, состоит в том, что инструкция "ДОБАВИТЬ" (отправляемая в ЦП) может привести к тому, что эти биты не будут изменены инструкцией (тогда как большинство других битов, которые я использую в этом примере, может изменить, за исключением некоторых битов флага).
D7 поместится в большем количестве битов, называемых регистром "D".
Регистр это просто кусок памяти. Регистры встроены в ЦП, поэтому ЦП может получать доступ к регистрам без необходимости взаимодействия с памятью на карте памяти.
Таким образом, математический результат 0xA5 умножить на 0xCB равен 0x82D7.
Теперь, почему биты были разделены на регистры A и D вместо регистров A и B или регистров C и D? Ну, еще раз, это пример сценария, который я использую, и должен был быть похож на концепцию реального языка ассемблера (Intel x86 16-битный, используемый Intel 8080 и 8088 и многими новыми процессорами). Могут существовать некоторые общие правила, такие как регистр "C", обычно используемый в качестве индекса для операций подсчета (типичный для циклов), и регистр "B", используемый для отслеживания смещений, которые помогают указывать области памяти. Таким образом, "А" и "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-битным процессором».