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 == truthy)を受け取ります BL
レジスタ(の下位バイトBX
、「冗長ブール」文字列を標準出力に出力します。
割り込み(0x21)を呼び出してDOS関数呼び出し(設定により選択)を実行することで機能します。 AH
2にしてDL
)を実行し、標準出力に1文字(in )を印刷します。
最初に、ASCII文字「0」がにロードされDL
、カウンター(CX
)が31に設定され、「冗長」バイトを印刷するためにループします。次に、入力ブール値が追加されますDL
(BL
falseyの場合、0を追加するDL
とASCII '0'のまま変更されません。BL
真の、DL
ASCII '1'に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で、プログラムが呼び出されたときにコマンドラインで指定された最初の(実際は2番目、スペースであるため)引数を見つけます。したがって、このバイトをASCII '0'と比較しているだけです。
比較によりフラグが設定され、次にSALC
命令(Pentiumより前のドキュメント化されていないオペコードsbb al, al
で、2の代わりに1バイトのみ)はAL
、2つの値が等しい場合は0に、異なる場合は-1に設定されます。AL
からを引くとDL
、必要に応じてASCII '0'または '1'になります。
(最初の文字だけを見るため、コマンドラインで先頭に0を付けて引数を渡すと、やや皮肉なことに、それを壊すことに注意してください。したがって01
、falseyとして扱われます。