Урок 4. 8 бит и сравнение: CMP — это вычитание

В картинках

После этого урока сумматор станет восьмибитным — числа от 0 до 255, — а три лампы будут отвечать, какое число больше: A = B, A < B или A > B. Ничего нового изобретать не придётся: два ADDSUB4 цепочкой и флаги вычитания.


4.1. Идея: две половины

Восемь бит — это две половины по четыре. Перенос из младшей половины (CO) идёт на вход переноса старшей (CI) — так же, как он бежит между разрядами внутри ADDER4. «Плюс 1» при вычитании нужен только один раз, в самом младшем разряде, поэтому SUB на CI идёт только у младшего ADDSUB4.

ADDSUB4старшие: биты 4–7ADDSUB4младшие: биты 0–3A4–A7, B4–B7A0–A3, B0–B3c4CO → CISUBна CICOVS4–S7S0–S3
ADDSUB8 — два ADDSUB4 цепочкой. Перенос младшей половины c4 идёт на CI старшей, как между разрядами внутри ADDER4. «Плюс 1» при вычитании (SUB на CI) — только у младшей половины. Флаги CO и V берём у старшей: там знаковый бит.

Переполнение 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
ADDSUB8A0
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
ORI0
I1
O0
S0
S1
z01
ORI0
I1
O0
S2
S3
z23
ORI0
I1
O0
S4
S5
z45
ORI0
I1
O0
S6
S7
z67
ORI0
I1
O0
z01
z23
z03
ORI0
I1
O0
z45
z67
z47
NOR (ноль)I0
I1
O0
z03
z47
Z

Шаг 3. Сравнение, лампы, табло

ДетальНогаМетка
NOTI0
O0
C
nC
NOTI0
O0
Z
nZ
AND (равно)I0
I1
O0
SUB
Z
EQ
AND (меньше)I0
I1
O0
SUB
nC
LT
ANDI0
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…A0BТумблеры B7…B0SUBТабло SЛампыЭто
2001100 1000550011 01110255N200 + 55 = 255
2001100 10001000110 0100044C300 не влезает в 8 бит: 256 ушло в перенос
1000110 01001000110 01000200N, Vсо знаком: 100 + 100 ≠ −56 — переполнение
70000 011170000 011110Z, C, A = Bравны
50000 010190000 10011252N, A < B5 − 9 = −4; заём, C = 0
90000 100150000 010114C, A > B9 − 5 = 4
1000110 01002001100 10001156N, A < B100 меньше 200
2001100 10001501001 0110150C, A > B200 больше 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)

Не получается? Что-то не работает →