2022/12/15

テクノロジー

人間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」内で第一回大会が開催されました。

    HCCC / 人間C言語コンパイラコンテスト

    詳しくは、以下の 公式説明スライド を参照ください。

    この大会ではチュートリアル問題も含めて全20問が出題されています。単純に数字を戻り値として返す問題から、四則演算、ローカル変数利用、文字列処理、ハローワールド、Fizzbuzzなど典型的なプログラムが多く出題されました。

    人間C言語コンパイラコンテスト Problems

    チュートリアル

    チュートリアル問題

    チュートリアル問題を解いていきましょう。実際に一問目として出題された 究極の疑問の答えを返すプログラム を題材とします。

    //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)、アセンブラ疑似命令に知識が必要です。

    以下、参考になるインターネットリソースを記載します。
    (※競技中はレギュレーションで認められたもののみ閲覧可能です)

    公式リソース

    その他のリソース

    ※本記事は2022年12月時点の情報です。

    著者:マイナビエンジニアブログ編集部