Машинный код x86-16 (DOS), 16 байт
B4 02 mov ah, 2
B2 30 mov dl, '0'
B9 1F 00 mov cx, 31
PrintZeros:
CD 21 int 0x21
E2 FC loop PrintZeros
00 CA add dl, bl
CD 21 int 0x21
C3 ret
Приведенная выше функция получает логическое значение (0 == Falsey, 1 == Truey) в BL
регистре ( байт BX
) и печатает «лишнюю логическую» строку в стандартный вывод.
Он работает, вызывая прерывание (0x21) для вызова функции DOS (выбирается настройкой AH
2), которая печатает один символ (in DL
) на стандартный вывод.
Сначала загружается символ ASCII '0' DL
, счетчик ( CX
) устанавливается в 31, и он зацикливается для вывода "лишних" байтов. Затем добавляется входное логическое значение DL
(если BL
false, добавление 0 не изменится DL
как ASCII '0'; если BL
верно, DL
будет увеличено на единицу до ASCII '1'), и будет напечатан последний байт.
Функция не возвращает значение.
Довольно приличный для языка, который на самом деле не делает строк.
Полная программа, 21 байт
Если вы хотите превратить его в полную программу, потребуется всего 5 байтов. Вместо того, чтобы передавать ввод в регистр, он читает входные данные из аргументов, переданных в командной строке при вызове приложения. Аргумент 0 интерпретируется как фальси, как и полное отсутствие аргументов; аргумент больше 0 интерпретируется как правдивый.
Просто соберите следующий код как программу COM, а затем выполните его в командной строке.
B4 02 mov ah, 2
B2 30 mov dl, '0'
B9 1F 00 mov cx, 31
PrintZeros:
CD 21 int 0x21
E2 FC loop PrintZeros
3A 16 82 00 cmp dl, BYTE PTR [0x82] ; compare to 2nd arg, at offset 0x82 in PSP
D6 salc ; equivalent to sbb al, al
28 C2 sub dl, al
CD 21 int 0x21
C3 ret ; you can simply 'ret' to end a COM program
Пример вывода:
C:\>bool.com
00000000000000000000000000000000
C:\>bool.com 0
00000000000000000000000000000000
C:\>bool.com 1
00000000000000000000000000000001
C:\>bool.com 2
00000000000000000000000000000001
C:\>bool.com 7
00000000000000000000000000000001
Как это работает? Ну, это в основном то же самое, пока вы не приступите к CMP
инструкции. Это сравнивает аргумент командной строки со значением DL
регистра (который, как вы помните, содержит ASCII '0'). В программе COM байты кода загружаются со смещением 0x100. За этим следует префикс сегмента программы (PSP) , который содержит информацию о состоянии программы DOS. В частности, по смещению 0x82 вы найдете первый (фактически второй, поскольку первый является пробелом) аргумент, который был указан в командной строке при запуске программы. Итак, мы просто сравниваем этот байт с ASCII '0'.
Сравнение устанавливает флаги, а затем SALC
инструкция (недокументированный код операции до Pentium, эквивалентный sbb al, al
, но только 1 байт вместо 2) устанавливает AL
значение 0, если два значения были равны, или -1, если они были разными. Тогда очевидно , что если вычесть AL
из DL
, это приводит либо ASCII «0» или «1», в зависимости от обстоятельств.
(Обратите внимание, что, по иронии судьбы, вы сломаете его, если передадите аргумент с начальным 0 в командной строке, так как он смотрит только на первый символ. Поэтому 01
будет рассматриваться как фальси. :-)