こちらがW言語のHello, Worldです。
write := 0x8B55, 0x8BEC, 0x085E, 0x4E8B, 0x8B04, 0x0656, 0x00B8,
0xCD40, 0x7321, 0x3102, 0x8BC0, 0x5DE5, 0x90C3
_() :=
{
write(1, "Hello, World!\r\n", 15)
}
「W言語」は、Viktor T. Toth氏によって設計されたシンプルでC言語のようなプログラミング言語です。
標準ライブラリが存在せず、OSのシステムコールを呼び出すためのコードをユーザー自身で書く必要があるという特徴があります。上記のHello World!はMS-DOS用の機械語を直接write関数に書き込んでいます。
write関数の機械語を逆アセンブルするとこのようになります。
多少は見やすくなった(?)ようなので、これを解説していきます。
0100 55 PUSH BP
0101 8BEC MOV BP,SP
0103 8B5E08 MOV BX,[BP+08]
0106 8B4E04 MOV CX,[BP+04]
0109 8B5606 MOV DX,[BP+06]
010C B80040 MOV AX,4000
010F CD21 INT 21
0111 7302 JNB 0115
0113 31C0 XOR AX,AX
0115 8BE5 MOV SP,BP
0117 5D POP BP
0118 C3 RET
0119 90 NOP
最初の2命令の、 PUSH BP と MOV BP,SP でスタックフレームを作成しています。要するに、今まで作業内容を一旦脇においておいて、新しい作業領域を作るようなイメージです。
その次の3命令 MOV BX,[BP+08] MOV CX,[BP+04] MOV DX,[BP+06] という処理で受け取った引数をBX, CX, DXレジスタに詰め込んでいます。 write 関数を呼び出しているコードを見ると、これらはそれぞれファイルハンドル、書き込む長さ、文字列のアドレスに対応しています。
そして、 MOV AX,4000 INT 21 でシステムコールの呼び出しを行います。AH=40h は「ファイルまたはデバイスへの書き込み」を意味しています。
https://en.wikipedia.org/wiki/DOS_API#DOS_INT_21h_services
その後は JNB 0115 でシステムコールの成功をチェックしています。Cフラグで成功か失敗かが分かるので、システムコールが正常に終了したかどうかの分岐をここで行っています。
処理が成功した場合には出力に成功したバイト数がAXレジスタに格納されるので、それをそのまま呼び出し元に返すため、0115にジャンプします。処理が失敗した場合には XOR AX,AX でAXレジスタをゼロクリアして戻り値ゼロ(エラー)を返すようにしています。ゼロクリアのためにMOV命令を使うこともできますが、XOR命令の方がバイナリサイズが小さくなるのでこのようなテクニックが使われています。
そして、 MOV SP,BP と POP BP でスタックポインタを元に戻して、 RET で呼び出しもとに返っています。最後のNOPは何もしない命令で、役割はないのですが、W言語は全ての変数が16ビットという仕様のため、16ビットの倍数にするための詰め物として使われています。