アセンブリでHello, world!

ELF Golfなるものが一部で流行っているらしいが,Plan9でやったら8.out Golfになるのかな?
libcを使わずシステムコール呼出しを書いたら,id:yupo5656さんにトラックバックしてもらったので,続きということで,アセンブリで書いてみる.コードは次に示すが,バイナリサイズは94バイトになった(C版は114バイト).SBはstatic baseと呼ばれる疑似レジスタで,プログラムの先頭アドレスを指している.mainや.stringのアドレスはロード時(8l実行時)に決定される.今回はmainが0x1020,.stringがデータセグメントの先頭の0x2000になっていた.ちなみに,システムコールの引数はレジスタを使わず,すべてスタック渡しになる.

	TEXT	main+0(SB),0,$0
	MOVL	$1,4(SP)
	MOVL	$.string+0(SB),8(SP)
	MOVL	$14,12(SP)
	MOVL	$20,AX
	INT	$64
	MOVL	$0,4(SP)
	MOVL	$8,AX
	INT	$64
	GLOBL	.string+0(SB),$16
	DATA	.string+0(SB)/8,$"Hello, w"
	DATA	.string+8(SB)/8,$"orld!\z\z\n"
	END	,

最後のDATA疑似命令の部分は8バイトでアライメントされるのか,次のように書いてもサイズに変化がなかった.

	GLOBL	.string+0(SB),$14
	DATA	.string+0(SB)/8,$"Hello, w"
	DATA	.string+8(SB)/6,$"orld!\n"

MOVLよりもPUSHLの方が命令長が短いので,PUSHLを使って書き直すと,77バイトまで縮まった.

	TEXT	main+0(SB),$0
	PUSHL	$14
	PUSHL	$.string+0(SB)
	PUSHL	$1
	PUSHL	$0
	MOVL	$20,AX
	INT	$64
	PUSHL	$0
	PUSHL	$0
	MOVL	$8,AX
	INT	$64

	GLOBL	.string+0(SB),$14
	DATA	.string+0(SB)/8,$"Hello, w"
	DATA	.string+8(SB)/6,$"orld!\n"
	END	,

どうせ,exits(2)から戻ることはないので,ちょっとちょんぼして,73バイト.

	TEXT	main+0(SB),$0
	PUSHL	$14
	PUSHL	$.string+0(SB)
	PUSHL	$1
	MOVL	$20,AX
_syscall:
	PUSHL	$0
	INT	$64
	MOVL	$8,AX
	JMP	_syscall

	GLOBL	.string+0(SB),$14
	DATA	.string+0(SB)/8,$"Hello, w"
	DATA	.string+8(SB)/6,$"orld!\n"
	END	,