プログラム: hello.c. これを「ソースコード」と呼ぶ.
#include<stdio.h>
int main(void)
{
printf("hello, world\n");
}
さすがに,このプログラム(ソースコード)の説明は必要ないはず...
こういうファイルをアスキーファイルと呼ぶが,
このファイルももちろん数字で書かれている.
確認のため od というコマンドを使い,ファイルの中身を見ておく.
% od -t x1z -A x hello.c 000000 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 69 6f 2e >#includeh>..int main(voi< 000020 64 29 0a 7b 0a 09 70 72 69 6e 74 66 28 22 68 65 >d).{..printf("he< 000030 6c 6c 6f 2c 20 77 6f 72 6c 64 5c 6e 22 29 3b 0a >llo, world\n");.< 000040 7d 0a >}.<
% gcc hello.c % ./a.out hello, world %ls -l -rwxr-xr-x 1 date date 4628 Jun 15 20:32 a.out*この a.out というファイルができているか確認する. 4626 という数字は,ファイルの大きさが 4626バイトという意味. 文字を10文字程度表示させるプログラム(実行ファイル)でも 4kバイトもメモリを費やしていることが分かる.
%od -t x1z -A x a.out 000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 >.ELF............< 000010 02 00 03 00 01 00 00 00 98 82 04 08 34 00 00 00 >............4...< 000020 54 07 00 00 00 00 00 00 34 00 20 00 07 00 28 00 >T.......4. ...(.< 000030 1b 00 18 00 06 00 00 00 34 00 00 00 34 80 04 08 >........4...4...< ....この 「gcc」 コマンドで作成した a.out は実行可能なファイルである. これから卒業までに gcc を使って,このような使い方以外のことをする機会は ないかもしれないが, 以下のこともできるというとを記憶の片隅に残しておこう.
% gcc -S hello.c
% less hello.s
.file "hello.c"
.section .rodata
.LC0:
.string "hello, world\n"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.size main, .-main
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.3.2 20031218 (Vine Linux 3.3.2-0vl8)"
細かいことはどうでもいい.
ここでは,命令がいろいろあることがわかればいい.
% gcc -c hello.c % ls -rw-r--r-- 1 date date 876 Jun 15 20:55 hello.oという 876バイトのファイルが作成されていることがわかる. これはアセンブリコード(アスキーファイル)と違って バイナリーファイルなので, 例によって od コマンドで中身を覗いてみる.
%od -t x1z -A x hello.o 000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 >.ELF............< 000010 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 >................< 000020 ec 00 00 00 00 00 00 00 34 00 00 00 00 00 28 00 >........4.....(.< 000030 0b 00 08 00 55 89 e5 83 ec 08 83 e4 f0 b8 00 00 >....U...........< 000040 00 00 29 c4 83 ec 0c 68 00 00 00 00 e8 fc ff ff >..)....h........< 000050 ff 83 c4 10 c9 c3 00 00 68 65 6c 6c 6f 2c 20 77 >........hello, w< 000060 6f 72 6c 64 0a 00 00 47 43 43 3a 20 28 47 4e 55 >orld...GCC: (GNU< ....さきに作成した a.out よりはコンパクトである.
この後,gcc は printf という関数を含んだ「ライブラリ」を hello.o に「リンク」して「ロードモジュール」を作成する. では実際に何がリンクされるのか. 少なくとも関数 printf のオブジェクトファイル printf.o が 含まれたライブラリがリンクされる必要がある. ディレクトリ /usr/lib 以下などに ライブラリは置かれている. stdio.h に関するものは libc.a ということで, そこから printf に関するものを コマンド ar を使って取り出してみる.
% ar x /usr/lib/libc.a printf.o %ls -al printf.o -rw-r--r-- 1 date date 696 Jun 17 21:42 printf.oこれだけで約700バイト. libc.a にどんな関数が含まれているか知りたければ,
% ar tv /usr/lib/libc.aとすれば分かる.
% ls -l /usr/lib/libc.a -rw-r--r-- 1 root root 2445076 Oct 29 2005 /usr/lib/libc.aというわけで libc.a はサイズが 2.4Mb ある. a.out は約4kb だったので, libc.a が全部リンクされているわけではないことが分かる.
% ldd a.out
libc.so.6 => /lib/i686/libc.so.6 (0x40023000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
例によって,わからないコマンドは man ldd と
すれば説明が表示される.
% nm hello.o
00000000 T main
U printf
% nm a.out 08049460 D _DYNAMIC 0804953c D _GLOBAL_OFFSET_TABLE_ 0804843c R _IO_stdin_used ...
% nm /usr/lib/libc.a ...オブジェクトファイルならなんでも適用できるので, なんでも試してみればいい.
% gcc -E hello.c | sed '/^[ ]*$/d' | lessとしてみれば分かる. これは前処理.
% readelf -a a.out ELF ヘッダ: マジック: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 クラス: ELF32 データ: 2 の補数、リトルエンディアン バージョン: 1 (current) ...
% gcc -c -g hello.c % objdump -d -l hello.o hello.o: ファイル形式 elf32-i386 セクション .text の逆アセンブル: 00000000何回も言いますが,細かいところはわからなくて問題ないです. まずは言葉になれてもらうこと, さらに, オブジェクトファイルの中身がどうなっているか調べるため, いろいろなコマンドが用意されていることを 伝えることが,このページの目的でした. 興味が湧いたら,それぞれの言葉,コマンドを より深くしらべてみてください.: main(): /home/date/public_html/lectures/2008ics/kadai/hello.c:4 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 08 sub $0x8,%esp 6: 83 e4 f0 and $0xfffffff0,%esp 9: b8 00 00 00 00 mov $0x0,%eax e: 29 c4 sub %eax,%esp /home/date/public_html/lectures/2008ics/kadai/hello.c:5 10: 83 ec 0c sub $0xc,%esp 13: 68 00 00 00 00 push $0x0 18: e8 fc ff ff ff call 19 1d: 83 c4 10 add $0x10,%esp /home/date/public_html/lectures/2008ics/kadai/hello.c:6 20: c9 leave 21: c3 ret
以下のページ,書籍を参考にしました.