Google Go言語でOSを書く
表題の通り。
とりあえず挑戦してみようと思います。
- -
実はコレ思いついたのが25日の夜で、
しかもオニャノコが
「クリスマス暇そうにしている君を救済してあげよう」
的に遊んでくれるらしくて、
その待ち合わせの時間つぶし中に思いついてしまいまして。
で、結局のところ、オニャノコと遊んでる間もずーっと頭から離れませんでした。
…ごめんなさい、嘘です。正直女の子の方が大s(ry
- -
gccgoをインストールする
実は…ムチャクチャ苦労しました。
Googleのサイト(http://golang.org/doc/gccgo_install.html)の手順にしたがって、subversionからチェックアウトしてきてmake -> make install
$ svn checkout svn://gcc.gnu.org/svn/gcc/branches/gccgo gccgo
$ mkdir objdir
$ cd objdir
$ ../gccgo/configure --enable-languages=c,c++,go --with-arch=i686
このconfigureの時に、32bit環境では--with-arch=i686オプションをつけると後でトラブルが起こらなさげ。
make installまで終わった後で、gccgoでコンパイルしようとすると次のように怒られたのですが、
/usr/local/gccgo/lib/gcc/i686-pc-linux-gnu/../../../libgo.so: undefined reference to '__sync_fetch_and_add8' /usr/local/gccgo/lib/gcc/i686-pc-linux-gnu/../../../libgo.so: undefined reference to'__sync_fetch_and_add_4' /usr/local/gccgo/lib/gcc/i686-pc-linux-gnu/../../../libgo.so: undefined reference to'__sync_bool_compare_and_swap_4'
-
- with-arch=i686オプションをつけることで回避できました。
$ make
(CoreDuo L2300で約3時間)
$ make install
これでgccgoコマンドが使えるようになるので、ライブラリを指定
$ LD_LIBRARY_PATH=/usr/local/lib
準備は整ったので適当にプログラム書く
$ vim helloworld.go
内容は省略。ご想像にお任せします。
$ gccgo helloworld.go
$ ./a.out
helloworld。はい。おk。
テストコードをコンパイル
とにかくテストコードをコンパイルします。
OSを書く上で、とりあえずのところ
package main func main(){ var x,y int; x = 10; y = 20; x = x*y; }
というような、どーでもいいコードにした。
(勿論、fmtとかインポートできないので。)
これをコンパイル。ただし-Wa,-aでアセンブルコードを吐かせ、-nostdincオプションをつけます。
本当は-nostdlibもつけたいのですが、つけられません。理由は後述。
$ gccgo -Wa,-a -nostdinc test.go
とりあえず何かしらバイナリは発生しました。
gccgoが吐く内容
とりあえず、GASが吐いたアセンブリコードを確認します。
1 .file "test.go" 2 .section .go_export,"",@progbits 3 0000 76313B0A .ascii "v1;\n" 4 0004 7061636B .ascii "package " 4 61676520 5 000c 6D61696E .ascii "main" 6 0010 3B0A .ascii ";\n" 7 0012 7072696F .ascii "priority 1;\n" 7 72697479 7 20313B0A 8 001e 66756E63 .ascii "func " 8 20 9 0023 2E6D6169 .ascii ".main.main" 9 6E2E6D61 9 696E 10 002d 2028 .ascii " (" 11 002f 29 .ascii ")" 12 0030 3B0A .ascii ";\n" 13 0032 66756E63 .ascii "func " 13 20 14 0037 6D61696E .ascii "main" 15 003b 2028 .ascii " (" 16 003d 29 .ascii ")" 17 003e 3B0A .ascii ";\n" 18 0040 63686563 .ascii "checksum EE27AD2EBD84C7C09629DFC1F55FB5CF97BE84ED;\n" 18 6B73756D 18 20454532 18 37414432 18 45424438 19 .text 20 .globl main.main 21 .type main.main, @function 22 main.main: 23 0000 653B2530 cmpl %gs:48, %esp 23 000000 24 0007 730A jae .L2 25 0009 6A00 pushl $0 26 000b 6A10 pushl $16 27 000d E8FCFFFF call __morestack 27 FF 28 0012 C3 ret 29 .L2: 30 0013 55 pushl %ebp 31 0014 89E5 movl %esp, %ebp 32 0016 83EC10 subl $16, %esp 33 0019 C745FC00 movl $0, -4(%ebp) 33 000000 34 0020 C745F800 movl $0, -8(%ebp) 34 000000 35 0027 C745FC0A movl $10, -4(%ebp) 35 000000 36 002e C745F814 movl $20, -8(%ebp) 36 000000 37 0035 8B45FC movl -4(%ebp), %eax 38 0038 0FAF45F8 imull -8(%ebp), %eax 39 003c 8945FC movl %eax, -4(%ebp) 40 003f C9 leave GAS LISTING /tmp/ccQWzczF.s page 2 41 0040 C3 ret 42 .size main.main, .-main.main 43 .globl __go_init_main 44 .type __go_init_main, @function 45 __go_init_main: 46 0041 653B2530 cmpl %gs:48, %esp 46 000000 47 0048 730A jae .L4 48 004a 6A00 pushl $0 49 004c 6A00 pushl $0 50 004e E8FCFFFF call __morestack 50 FF 51 0053 C3 ret 52 .L4: 53 0054 55 pushl %ebp 54 0055 89E5 movl %esp, %ebp 55 0057 5D popl %ebp 56 0058 C3 ret 57 .size __go_init_main, .-__go_init_main 58 .ident "GCC: (GNU) 4.5.0 20091110 (experimental)" 59 .section .note.GNU-stack,"",@progbits 60 .section .note.GNU-split-stack,"",@progbits
…。
……。汗汗;;。
CやC++の後続ーとか言うのでもっと綺麗なコード吐くのだと思ってましたが、全然いやいやそんなことなかった><;
とりあえず気になるのは50行目の call __morestack ですね。
gccgoでコンパイルする時に、-nostdlibオプションをつけるとコンパイルが通らないのですが、
はおそらくコイツが原因ですね。
これではOSは書けませんですよねー。困りました。
とりあえず今日は時間がないのでここまでですが、
morestackの仕事の調べはついているので、とりあえずダミーを作ってリンクし、-nostdlibをつけてコンパイルが通るかってのと、
コードセクション意外を殺せるのかを調べてみたいと思います。
正直、思ってたよりも難しそうです。あう。