Większość treści tej odpowiedzi oryginalnie pochodziła z tej odpowiedzi (napisanej przed tamtym innym pytaniem oznaczonym jako duplikat). Omawiam więc użycie wartości 8-bitowych (chociaż pytanie to dotyczyło wartości 32-bitowych), ale to dobrze, ponieważ wartości 8-bitowe są prostsze do zrozumienia koncepcyjnego, a te same pojęcia dotyczą większych wartości, takich jak 32-bitowa arytmetyka.
Po dodaniu dwóch liczb, które są 8-bitowe, największa liczba jaką można uzyskać (0xFF + 0xFF = 1FE). W rzeczywistości, jeśli pomnożymy dwie liczby 8-bitowe, to największa liczba jaką możemy otrzymać (0xFF * 0xFF = 0xFE01) to nadal 16 bitów, dwa razy więcej niż 8 bitów.
Teraz możesz założyć, że procesor x-bitowy może śledzić tylko x bitów. (Na przykład, 8-bitowy procesor może śledzić tylko 8 bitów.) To nie jest dokładne. Procesor 8-bitowy odbiera dane w 8-bitowych fragmentach. (Te “fragmenty” mają zazwyczaj formalne określenie: “słowo”. W przypadku procesora 8-bitowego używane są 8-bitowe słowa. Na procesorze 64-bitowym, 64-bitowe słowa mogą być użyte)
Tak więc, gdy dasz komputerowi 3 bajty:
Bajt #1: instrukcja MUL
Bajt #2: bajty wysokiego rzędu (np. 0xA5)
Bajt #3: bajty niższego rzędu (np. 0xCB)
Komputer może wygenerować wynik, który jest większy niż 8 bitów. Procesor może wygenerować wyniki w następujący sposób:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx 1101 0111
a.k.a.:
0x4082xxxxxxD7
Teraz pozwól, że zinterpretuję to dla Ciebie:
0x oznacza tylko, że następujące cyfry są w systemie szesnastkowym.
Za chwilę omówię bardziej szczegółowo “40”.
82 jest częścią rejestru “A”, który jest serią 8 bitów.
xx i xx są częścią dwóch innych rejestrów, zwanych rejestrem “B” i rejestrem “C”. Powodem, dla którego nie wypełniłem tych bitów zerami lub jedynkami jest to, że instrukcja “ADD” (wysyłana do procesora) może spowodować, że bity te nie zostaną zmienione przez instrukcję (podczas gdy większość innych bitów, których używam w tym przykładzie, może zostać zmieniona, z wyjątkiem niektórych bitów flag).
D7 zmieściłoby się w większej ilości bitów, zwanych rejestrem “D”.
Rejestr to tylko kawałek pamięci. Rejestry są wbudowane w procesory, więc procesor może uzyskać dostęp do rejestrów bez potrzeby interakcji z pamięcią na pendrive'ie RAM.
Tak więc wynik matematyczny 0xA5 razy 0xCB to 0x82D7.
Teraz, dlaczego bity zostały podzielone na rejestry A i D zamiast na rejestry A i B, albo na rejestry C i D? Cóż, po raz kolejny, jest to przykładowy scenariusz, którego używam, mający być raczej podobny w koncepcji do prawdziwego języka assemblingu (16-bitowy Intel x86, używany przez procesory Intel 8080 i 8088 oraz wiele nowszych procesorów). Mogą istnieć pewne wspólne reguły, takie jak rejestr “C” używany zazwyczaj jako indeks do operacji liczenia (typowy dla pętli), czy rejestr “B” używany do śledzenia offsetów, które pomagają określić lokalizację pamięci. Tak więc, “A” i “D” mogą być bardziej powszechne dla niektórych typowych funkcji arytmetycznych.
Każda instrukcja CPU powinna mieć jakąś dokumentację, używaną przez osoby programujące w Assembly. Dokumentacja ta powinna określać, jakie rejestry są wykorzystywane przez każdą instrukcję. (Tak więc wybór, które rejestry mają być używane, jest często określany przez projektantów CPU, a nie przez programistów języka Assembly. )
Teraz, wracając do “40” w powyższym przykładzie: jest to seria bitów, często nazywana “rejestrem flag”. Każdy bit w rejestrze flag ma swoją nazwę. Na przykład, istnieje bit “overflow”, który CPU może ustawić, jeśli wynik jest większy niż miejsce, które może przechowywać jeden bajt wyników. (Bit “overflow” często może być oznaczony skróconą nazwą “OF”. To jest kapitał o, a nie zero). Oprogramowanie może sprawdzić wartość tej flagi i zauważyć “problem”. Praca z tym bitem jest często obsługiwana w niewidoczny sposób przez języki wyższego poziomu, więc początkujący programiści często nie uczą się interakcji z flagami procesora. Jednakże, programiści Assembly mogą często uzyskać dostęp do niektórych z tych flag w sposób bardzo podobny do innych zmiennych.
Na przykład, możesz mieć wiele instrukcji ADD. Jedna instrukcja ADD może przechowywać 16 bitów wyników w rejestrze A i rejestrze D, podczas gdy inna instrukcja może przechowywać tylko 8 bitów niskich w rejestrze A, ignorować rejestr D i określać bit przepełnienia. Następnie, później (po zapisaniu wyników z rejestru A w głównej pamięci RAM), można użyć innej instrukcji ADD, która przechowuje w rejestrze tylko 8 bitów wysokich (ewentualnie w rejestrze A).
(Zwykle jest też flaga “underflow”, w przypadku gdy odejmiesz zbyt dużo, aby zmieścić się w pożądanym wyniku)
Aby pokazać Ci jak bardzo skomplikowane rzeczy się skomplikowały:
Intel 4004 był 4-bitowym procesorem
Intel 8008 był 8-bitowym procesorem. Miał 8-bitowe rejestry o nazwach A, B, C i D.
Intel 8086 był procesorem 16-bitowym. Miał 16-bitowe rejestry o nazwach A, B, C i D. AX, BX, CX i DX.
Intel 80386 był 32-bitowym procesorem. Miał 32-bitowe rejestry nazwane EAX, EBX, ECX i EDX.
Procesory Intel x64 mają 64-bitowe rejestry nazwane RAX, RBX, RCX i RDX. Układy x64 mogą uruchamiać 16-bitowy kod (w niektórych trybach pracy) i mogą interpretować 16-bitowe instrukcje. Bity składające się na rejestr AX to połowa bitów składających się na rejestr EAX, które są połową bitów składających się na rejestr RAX. Zatem za każdym razem, gdy zmieniasz wartość AX, zmieniasz również EAX i RAX, ponieważ bity używane przez AX są częścią bitów używanych przez RAX. (Jeśli zmienisz EAX o wartość, która jest wielokrotnością 65,536, wówczas dolne 16 bitów pozostanie niezmienione, więc AX nie zmieni się. Jeśli zmienisz EAX o wartość, która nie jest wielokrotnością 65,536, to wpłynie to również na AX.)
Istnieje więcej flag i rejestrów niż tylko te, które wymieniłem. Po prostu wybrałem kilka powszechnie używanych, aby dać prosty koncepcyjny przykład.
Teraz, jeśli jesteś na 8-bitowym CPU, kiedy piszesz do pamięci, możesz znaleźć pewne ograniczenia dotyczące możliwości odwołania się do adresu 8-bitowego, a nie adresu 4-bitowego lub 16-bitowego. Szczegóły będą się różnić w zależności od procesora, ale jeśli masz takie ograniczenia, to procesor może mieć do czynienia z 8-bitowymi słowami, dlatego też najczęściej określa się go jako “8-bitowy procesor”.