借り初めのひみつきち

仮ブログです。

UEFI ゴルフの果てに

前回の記事の UEFI ゴルフの続報です。

Hello world はどの環境でも文字列出力関数(API, メソッド, etc...)を呼び出すだけなのでコードはほぼ定型となりコード部分の最適化の余地はほとんどありませんでした。
ゴルフのお題のひとつに CHARS というものがあり、これは印字可能 ASCII 文字の一覧を出力するものです。
CHARS は固定の文字列データが存在しないのでロジックの最適化で Hello world より小さくできる可能性が高いです。

ということで、試行錯誤の末にヘッダの圧縮とセットで 268 バイトまで削減することができました。

EfiMain:
    push rbx
    push rdi
    enter 0x20, 0

    mov rdi, rdx
    mov ebx, 0x20
.loop:
    mov rcx, [rdi + 0x40] ; EFI_SYSTEM_TABLE->ConOut
    lea rdx, [rbp + 0x20]
    mov [rdx], ebx
    call [rcx + 0x08] ; EFI_SIMPLE_OUTPUT_PROTOCOL->OutputString
    inc ebx
    cmp bl, 0x7F
    jb .loop

    xor eax, eax
    leave
    pop rdi
    pop rbx
    ret

なお、最後に改行を入れてないのでシェルのプロンプトによって表示が一部破壊されてしまいます。これがレギュレーション的に OK だったかどうかよく覚えてません...

f:id:neriring16:20191128231935p:plain

実際には push/pop を使わないバージョンも一応動きはするのですが、なぜか起動しません。

f:id:neriring16:20191128232634p:plain

そこですぐに ret する何もしないアプリケーションを作って nop の量を調整して調査した所、どういうわけかテキストセクションのサイズが 0x28 (40) バイトに満たないバイナリは問答無用でエラーになるようです。

つまり、これ以上ロジックを最適化しても意味がないということで、ゴルフ終了・・・?

ねり先生の次回作にご期待ください。

成果物を GitHub に公開しておきます。

github.com