テクノロジー
人間Cコンパイラになる方法
はじめに
本日12月15日は C++14 (ISO/IEC 14882:2014) と C++20 (ISO/IEC 14882:2020) のリリース日です。
C++14 は8年前の2014年12月15日、C++20 は2年前の2020年12月15日 にリリースされました。
C言語といえば、先日(2022/11/19)に「人間Cコンパイラコンテスト」に参加し、ランキング1位を獲得することができました。このエントリーでは人間Cコンパイラのはじめかたをまとめていきます。
人間Cコンパイラコンテストとは?
「人間Cコンパイラコンテスト」(HCCC)とは競技者自身がCコンパイラとなり C言語からアセンブリを生成し、その時間と正確さを競う競技です。日本ネットワークセキュリティ協会(JNSA) の SECCON実行委員会が実施する「SECCONCON」内で第一回大会が開催されました。
詳しくは、以下の 公式説明スライド を参照ください。
この大会ではチュートリアル問題も含めて全20問が出題されています。単純に数字を戻り値として返す問題から、四則演算、ローカル変数利用、文字列処理、ハローワールド、Fizzbuzzなど典型的なプログラムが多く出題されました。
チュートリアル
チュートリアル問題
チュートリアル問題を解いていきましょう。実際に一問目として出題された 究極の疑問の答えを返すプログラム を題材とします。
//return_42.c
int main(void) {
return 42;
}
開発環境の構築
これくらい単純なプログラムであればそのままポータルサイトに入力しても問題ありませんが、複雑なプログラムではローカル環境でのデバッグが必須です。ここでは公式が提供している検証環境を利用して開発環境を構築します。
~$ git clone https://github.com/HumanCCompilerContest/HCCC_local_env
~$ cd HCCC_local_env
~/HCCC_local_env$ docker build -t hccc_local_env .
~/HCCC_local_env$ docker run -it --rm hccc_local_env
アセンブリコードの作成
開発環境では vim や emacs などコーディングエディタが利用できます。
ここでは、vim を利用して ファイル return_42.s を新規作成し、先のC言語のソースファイルをx86_64アークテクチャのアセンブリに変換してコーディングしていきます。
root@a741545b3735 ~
$ vim hccc/return_42.s
▼return_42.s
.globl main
main:
push %rbp
mov %rsp, %rbp
mov $42, %rax
mov %rbp, %rsp
pop %rbp
ret
アセンブルと実行
開発環境では アセンブリコードのアセンブル&実行するコマンド「asm2bin」 が用意されています。
作成したアセンブリコードファイルを引数にして実行します。
root@a741545b3735 ~
$ asm2bin hccc/return_42.s
実行後、返り値として「42」が返っていることが確認できました。
root@a741545b3735 ~
$ echo $?
42
デバッグ
開発環境では PEDA 拡張された gdb が利用できます。
asm2bin 実行すると、実行オブジェクトファイルはカレントディレクトに「tmp」として保存されていますので、これをデバッグ実行します。
$ gdb tmp
$ break main
$ run
命令ポインタ前後の命令やレジスタ値、スタックフレームなどが可視化させれているため、効率的なデバッグが可能です。
人間コンパイルの知識リソース
C言語からx86_64アセンブリにコンパイルするためには、C言語(C99)、CPU命令(x86_64)、ABI (System V Application Binary Interface)、アセンブラ疑似命令に知識が必要です。
以下、参考になるインターネットリソースを記載します。
(※競技中はレギュレーションで認められたもののみ閲覧可能です)
公式リソース
その他のリソース
- x86 Assembly Language Reference Manual : Assembler Directives
- AMD64 ABI の特徴
- 低レイヤを知りたい人のためのCコンパイラ作成入門
※本記事は2022年12月時点の内容です。