💻

システムコールでHelloWorld

2021/08/09に公開

Linuxシステムプログラミングを輪読することになり1章担当になりました。
https://www.amazon.co.jp/dp/4873113628

1章なのでなんとなくで軽く読み流してもよかったのですが、せっかくなので少しだけ深ぼってみた。後々の章で説明がありそうなきもするけれど念のため。

i386(32bit)システムでは、ユーザーアプリケーションがソフトウェア割り込み命令intを実行します。割り込み番号は 0x80 (int 0x80という命令が実行される)。

これがなんなのか分からなかった。0x80をどうやって送って命令出すんだろう?

アセンブリ言語でHello,Worldしてみる

上記のサイトを参考にしつつ少してを加えて変えてみた。実行環境はUbuntu20.04。
アセンブリ言語まで下ると int $0x80 という命令がかかれて意味を理解できた。これを添えて実行するとCPUに割り込んで標準出力させることができる。

.globl _start
_start:
    /* $の後が数字なら数字、文字なら変数。%はレジスタ */
    movl $4,%eax   /* write システムコール番号 */
    movl $1,%ebx   /* 書き込み先 - 標準出力 */
    movl $msg,%ecx /* 書き込むメッセージ */
    movl $13,%edx  /* メッセージの長さ */
    int $0x80      /* システムコール実行 割り込み実行 */

    movl $1,%eax /* システムコール終了番号 */
    movl $0,%ebx /* 終了状態 */
    int $0x80    /* システムコール終了 割り込み実行 */

.data
    msg: .asciz "Hello,World\n"
➜ ~ as -o main.o main.S
➜ ~ ld -o main.out main.o
➜ ~ ./main.out
hello,World
➜ ~

C言語とシステムコールでHello,Worldしてみる

こちらはシステムコールでHelloWorldするC言語。write関数なので自動的にeax=4、第一引数の1が標準出力 ebx=1, 出力文字列stringをecx、文字列の長さをedx

先にアセンブリ言語をみておくとwrite関数の引数の意味も見えてくる。

#include<unistd.h>

int main(){
  const void *string = "Hello,World!\n";
  write(1, string, 13);
  return 0;
}
➜ ~ gcc write.c
➜ ~ ./a.out
Hello World!
➜ ~

逆アセンブルしてみる

最初に書いたアセンブリ言語は32bitの書き方なので、64bitでコンパル->逆アセンブルするとだいぶ結果が異なる。int 0x80は見当たらないけど, 0x8がmovされているので、これがどこかで実行されている?のでしょう

int main(){
   0:   f3 0f 1e fa             endbr64
   4:   55                      push   %rbp
   5:   48 89 e5                mov    %rsp,%rbp
   8:   48 83 ec 10             sub    $0x10,%rsp
  const void *string = "Hello Write!\n";
   c:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # 13 <main+0x13>
  13:   48 89 45 f8             mov    %rax,-0x8(%rbp)
  write(1, string, 13);
  17:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  1b:   ba 0d 00 00 00          mov    $0xd,%edx
  20:   48 89 c6                mov    %rax,%rsi
  23:   bf 01 00 00 00          mov    $0x1,%edi
  28:   e8 00 00 00 00          callq  2d <main+0x2d>
  return 0;
  2d:   b8 00 00 00 00          mov    $0x0,%eax
}
  32:   c9                      leaveq
  33:   c3                      retq

まとめ

新しめの日本語情報でHello,Worldする情報があんまりなかったので書き残してみた。なお輪読する「Linuxシステムプログラミング」ではC言語をほうをメインに取り扱うのでアセンブリ言語はもう登場しないと思う……

Discussion