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