x86-16 Kod maszynowy (DOS), 16 bajtów
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
Powyższa funkcja otrzymuje w BLrejestrze wartość logiczną (0 == falsey, 1 == prawda) BXi wypisuje na standardowym wyjściu ciąg znaków „redundantny”.
Działa poprzez wywołanie przerwania (0x21), aby wykonać wywołanie funkcji DOS (wybrane przez ustawienie AHna 2), które wypisuje pojedynczy znak (wDL ) na standardowe wyjście.
Najpierw ładowany jest znak ASCII „0” DL, licznik ( CX) jest ustawiony na 31 i zapętla się, aby wydrukować „nadmiarowe” bajty. Następnie dodawana jest wartość logiczna wejściowa DL(jeśli BLjest falsey, dodanie 0 pozostawi DLniezmienioną jako ASCII „0”; jeśli BLjest prawdą, DLzostanie zwiększone o jeden do ASCII „1”), i zostanie wydrukowany ostatni bajt.
Funkcja nie zwraca wartości.
Całkiem przyzwoicie jak na język, który tak naprawdę nie robi nici.
Pełny program, 21 bajtów
Jeśli chcesz przekształcić go w pełny program, potrzeba tylko 5 dodatkowych bajtów. Zamiast przekazywać dane wejściowe do rejestru, odczytuje dane wejściowe z argumentów przekazanych w wierszu poleceń podczas wywoływania aplikacji. Argument 0 jest interpretowany jako falsey, podobnie jak całkowity brak argumentów; argument większy niż 0 jest interpretowany jako prawdziwy.
Po prostu złóż poniższy kod jako program COM, a następnie uruchom go w wierszu poleceń.
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
Przykładowe dane wyjściowe:
C:\>bool.com
00000000000000000000000000000000
C:\>bool.com 0
00000000000000000000000000000000
C:\>bool.com 1
00000000000000000000000000000001
C:\>bool.com 2
00000000000000000000000000000001
C:\>bool.com 7
00000000000000000000000000000001
Jak to działa? Cóż, to w zasadzie to samo, dopóki nie przejdziesz do CMPinstrukcji. Porównuje to argument wiersza poleceń z wartością parametruDL rejestru (który, jak pamiętacie, zawiera ASCII „0”). W programie COM bajty kodu są ładowane z przesunięciem 0x100. Poprzednikiem jest prefiks segmentu programu (PSP) , który zawiera informacje o stanie programu DOS. W szczególności przy przesunięciu 0x82 znajduje się pierwszy (właściwie drugi, ponieważ pierwszy jest spacją) argument, który został podany w wierszu poleceń podczas wywoływania programu. Właśnie porównujemy ten bajt z ASCII „0”.
Porównanie ustawia flagi, a następnie SALCinstrukcja (nieudokumentowany kod operacyjny przed Pentium, równoważny sbb al, al, ale tylko 1 bajt zamiast 2) ustawia ALna 0, jeśli dwie wartości były równe, lub -1, jeśli były różne. Jest wtedy oczywiste, że kiedy odejmujemyAL od DLpowoduje to zarówno ASCII „0” lub „1”, odpowiednio.
(Zauważ, że nieco ironicznie złamiesz go, jeśli podasz argument z wiodącym 0 w wierszu poleceń, ponieważ wygląda tylko na pierwszy znak. 01Będzie to traktowane jak falsey. :-)