Урок 4. 8 бит и сравнение: CMP — это вычитание
В картинкахПосле этого урока сумматор станет восьмибитным — числа от 0 до 255, — а три лампы будут отвечать, какое число больше: A = B, A < B или A > B. Ничего нового изобретать не придётся: два ADDSUB4 цепочкой и флаги вычитания.
4.1. Идея: две половины
Восемь бит — это две половины по четыре. Перенос из младшей половины (CO) идёт на вход переноса старшей (CI) — так же, как он бежит между разрядами внутри ADDER4. «Плюс 1» при вычитании нужен только один раз, в самом младшем разряде, поэтому SUB на CI идёт только у младшего ADDSUB4.
Переполнение V считается по старшему, знаковому биту — поэтому берём его у старшей половины, а V младшей не нужен.
4.2. Идея: сравнение — это вычитание
Чтобы сравнить два числа, вычти B из A и посмотри на флаги:
A = B— результат ноль, горитZ;A < B— пришлось занимать,C = 0;A > B— заёма не было (C = 1), и результат не ноль.
Так сравнивают числа все процессоры. Команда CMP (compare) — это вычитание, от которого остаются только флаги, а результат выбрасывается. Следующая команда смотрит на флаги и решает, куда перейти.
4.3. Сборка
Тот же проект. Стенд урока 3 (9 тумблеров, ADDSUB4 на холсте, OR/OR/NOR, лампы, три табло) удали; Power/Ground оставь.
Идея. Восемь бит — это две половины по четыре. Перенос из младшей половины (CO) идёт на вход переноса старшей (CI) — так же, как перенос бежит между разрядами внутри ADDER4. «Плюс 1» при вычитании нужен только один раз — в самом младшем разряде, поэтому SUB на CI идёт только у младшего ADDSUB4.
Сравнение — это вычитание. Вычти B из A и посмотри на флаги:
A = B— результат ноль, горитZ;A < B— был заём,C = 0;A > B— заёма не было (C = 1) и результат не ноль.
Так сравнивают числа все процессоры: команда CMP — это вычитание, которое не сохраняет результат, а оставляет только флаги.
Шаг 1. ADDSUB8 — два ADDSUB4 цепочкой
| Деталь | Нога | Метка |
|---|---|---|
| Порт входа | выход | A0 |
| Порт входа | выход | A1 |
| Порт входа | выход | A2 |
| Порт входа | выход | A3 |
| Порт входа | выход | A4 |
| Порт входа | выход | A5 |
| Порт входа | выход | A6 |
| Порт входа | выход | A7 |
| Порт входа | выход | B0 |
| Порт входа | выход | B1 |
| Порт входа | выход | B2 |
| Порт входа | выход | B3 |
| Порт входа | выход | B4 |
| Порт входа | выход | B5 |
| Порт входа | выход | B6 |
| Порт входа | выход | B7 |
| Порт входа | выход | SUB |
| ADDSUB4 (младшие 4 бита) | A0 A1 A2 A3 B0 B1 B2 B3 SUB CI S0 S1 S2 S3 CO V | A0 A1 A2 A3 B0 B1 B2 B3 SUB SUB S0 S1 S2 S3 c4 — (свободна) |
| ADDSUB4 (старшие 4 бита) | A0 A1 A2 A3 B0 B1 B2 B3 SUB CI S0 S1 S2 S3 CO V | A4 A5 A6 A7 B4 B5 B6 B7 SUB c4 S4 S5 S6 S7 CO V |
| Порт выхода | вход | S0 |
| Порт выхода | вход | S1 |
| Порт выхода | вход | S2 |
| Порт выхода | вход | S3 |
| Порт выхода | вход | S4 |
| Порт выхода | вход | S5 |
| Порт выхода | вход | S6 |
| Порт выхода | вход | S7 |
| Порт выхода | вход | CO |
| Порт выхода | вход | V |
Ctrl+G → имя ADDSUB8. Ноги: входы A0–A7, B0–B7, SUB; выходы S0–S7, CO, V.
У младшего ADDSUB4 нога V остаётся свободной: переполнение считаем по знаковому биту, а он — в старшей половине.
Шаг 2. Холст: тумблеры, сумматор, флаг Z
| Деталь | Нога | Метка |
|---|---|---|
| Input | выход | A0 |
| Input | выход | A1 |
| Input | выход | A2 |
| Input | выход | A3 |
| Input | выход | A4 |
| Input | выход | A5 |
| Input | выход | A6 |
| Input | выход | A7 |
| Input | выход | B0 |
| Input | выход | B1 |
| Input | выход | B2 |
| Input | выход | B3 |
| Input | выход | B4 |
| Input | выход | B5 |
| Input | выход | B6 |
| Input | выход | B7 |
| Input | выход | SUB |
| ADDSUB8 | A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 SUB S0 S1 S2 S3 S4 S5 S6 S7 CO V | A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 SUB S0 S1 S2 S3 S4 S5 S6 S7 C V |
| OR | I0 I1 O0 | S0 S1 z01 |
| OR | I0 I1 O0 | S2 S3 z23 |
| OR | I0 I1 O0 | S4 S5 z45 |
| OR | I0 I1 O0 | S6 S7 z67 |
| OR | I0 I1 O0 | z01 z23 z03 |
| OR | I0 I1 O0 | z45 z67 z47 |
| NOR (ноль) | I0 I1 O0 | z03 z47 Z |
Шаг 3. Сравнение, лампы, табло
| Деталь | Нога | Метка |
|---|---|---|
| NOT | I0 O0 | C nC |
| NOT | I0 O0 | Z nZ |
| AND (равно) | I0 I1 O0 | SUB Z EQ |
| AND (меньше) | I0 I1 O0 | SUB nC LT |
| AND | I0 I1 O0 | C nZ cnz |
| AND (больше) | I0 I1 O0 | SUB cnz GT |
| LED (C — перенос) | вход | C |
| LED (Z — ноль) | вход | Z |
| LED (N — знак) | вход | S7 |
| LED (V — переполнение) | вход | V |
| LED (A = B) | вход | EQ |
| LED (A < B) | вход | LT |
| LED (A > B) | вход | GT |
| Display | ⚙ | ширина 8, DEC, шина A |
| Display | ⚙ | ширина 8, DEC, шина B |
| Display | ⚙ | ширина 8, DEC, шина S |
Лампы сравнения проходят через AND с SUB: при сложении они не горят — сравнивать имеет смысл только вычитанием.
4.4. Проверка
Табло показывает числа без знака: 0…255. Со знаком 1xxxxxxx — это отрицательные (−128…−1), и тогда горит N.
| A | Тумблеры A7…A0 | B | Тумблеры B7…B0 | SUB | Табло S | Лампы | Это |
|---|---|---|---|---|---|---|---|
| 200 | 1100 1000 | 55 | 0011 0111 | 0 | 255 | N | 200 + 55 = 255 |
| 200 | 1100 1000 | 100 | 0110 0100 | 0 | 44 | C | 300 не влезает в 8 бит: 256 ушло в перенос |
| 100 | 0110 0100 | 100 | 0110 0100 | 0 | 200 | N, V | со знаком: 100 + 100 ≠ −56 — переполнение |
| 7 | 0000 0111 | 7 | 0000 0111 | 1 | 0 | Z, C, A = B | равны |
| 5 | 0000 0101 | 9 | 0000 1001 | 1 | 252 | N, A < B | 5 − 9 = −4; заём, C = 0 |
| 9 | 0000 1001 | 5 | 0000 0101 | 1 | 4 | C, A > B | 9 − 5 = 4 |
| 100 | 0110 0100 | 200 | 1100 1000 | 1 | 156 | N, A < B | 100 меньше 200 |
| 200 | 1100 1000 | 150 | 1001 0110 | 1 | 50 | C, A > B | 200 больше 150 |
В колонках «Тумблеры» слева — старший тумблер (A7), справа — A0; 1 — включён, 0 — выключен.
Если ответ неверен только в старших битах — проверь CI старшего ADDSUB4: он должен быть на метке c4.
Вставка урока 4 (Cmd+I)
Нужны NOT, AND, OR, NOR и ADDSUB4. Стенд урока 3 удали, кроме питания.
# Урок 4 — 8 бит и сравнение. Два ADDSUB4 цепочкой → ADDSUB8; сравнение через вычитание.# Вставка: Cmd+I поверх урока 3 (нужны NOT, AND, OR, NOR, ADDSUB4). Стенд урока 3 удалить, кроме питания. # --- 8 бит: перенос младшей половины идёт на CI старшей ---chip ADDSUB8 { portIn(A0) portIn(A1) portIn(A2) portIn(A3) portIn(A4) portIn(A5) portIn(A6) portIn(A7) portIn(B0) portIn(B1) portIn(B2) portIn(B3) portIn(B4) portIn(B5) portIn(B6) portIn(B7) portIn(SUB) portOut(S0) portOut(S1) portOut(S2) portOut(S3) portOut(S4) portOut(S5) portOut(S6) portOut(S7) portOut(CO) portOut(V) # младшие 4 бита: «плюс 1» при вычитании — SUB на CI ADDSUB4(A0=A0, A1=A1, A2=A2, A3=A3, B0=B0, B1=B1, B2=B2, B3=B3, SUB=SUB, CI=SUB, S0=S0, S1=S1, S2=S2, S3=S3, CO=c4) # старшие 4 бита: CI — перенос из младших; V считаем по старшему (знаковому) биту ADDSUB4(A0=A4, A1=A5, A2=A6, A3=A7, B0=B4, B1=B5, B2=B6, B3=B7, SUB=SUB, CI=c4, S0=S4, S1=S5, S2=S6, S3=S7, CO=CO, V=V)} # --- на холст: тумблеры A, B (по 8), SUB; сумматор; флаги; сравнение ---input(A0)input(A1)input(A2)input(A3)input(A4)input(A5)input(A6)input(A7)input(B0)input(B1)input(B2)input(B3)input(B4)input(B5)input(B6)input(B7)input(SUB)ADDSUB8(A0=A0, A1=A1, A2=A2, A3=A3, A4=A4, A5=A5, A6=A6, A7=A7, B0=B0, B1=B1, B2=B2, B3=B3, B4=B4, B5=B5, B6=B6, B7=B7, SUB=SUB, S0=S0, S1=S1, S2=S2, S3=S3, S4=S4, S5=S5, S6=S6, S7=S7, CO=C, V=V)# Z: все 8 разрядов — нольOR(S0, S1, z01)OR(S2, S3, z23)OR(S4, S5, z45)OR(S6, S7, z67)OR(z01, z23, z03)OR(z45, z67, z47)NOR(z03, z47, Z)# сравнение (при SUB = 1): равно — Z; меньше — был заём (C = 0); больше — C = 1 и не нольNOT(C, nC)NOT(Z, nZ)AND(SUB, Z, EQ)AND(SUB, nC, LT)AND(C, nZ, cnz)AND(SUB, cnz, GT)led(C)led(Z)led(S7)led(V)led(EQ)led(LT)led(GT)Не получается? Что-то не работает →