2002-11-12 [長年日記]
λ. システムプログラミングSA
顔を覚えた人が見当たらなかったので今日は少々寂しかった。それにしても今度は電卓プログラムか、そろそろ添削したくなくなってきたぞー
λ. 東方紅魔郷
ハードではクリア出来なかったので、ノーマルまでレベルを落としたら、今度はラスボスに敗北。シューティングはむずい。
λ. ソースコード読み会: Linuxのprocfs
ファイルシステム班が読み会をやると言うので何となく付いて行ってみる。これでLinuxのファイルシステム周りの基本的な構造は理解できた(ような気がする)。
λ. Re: 次のプログラムをi386上で実行するとどうなるか,その理由もあわせて答えよ
例えば以下のコードが生成された(cygwinで"gcc -O0"でコンパイルした場合)とすると 「addl $16,4(%ebp)」で関数のリターンアドレスを16進めてしまうことになるはず。結果としてその間にあった「exit(1);」がスキップされて、"hoge"がプリントされるのでしょう。
_test: pushl %ebp movl %esp,%ebp subl $1608,%esp addl $16,4(%ebp) movl %ebp,%esp popl %ebp ret
アドレス | 説明 |
---|---|
-1608(%ebp) | ?(%espの指している先) |
-1604(%ebp) | ? |
-1600(%ebp) | 自動変数s4を格納する領域 |
0(%ebp) | 古い%ebpの値が入ってる |
4(%ebp) | 関数のリターンアドレスが入ってる |
8(%ebp) | 第1引数s0を格納する領域 |
12(%ebp) | 第2引数s1を格納する領域 |
16(%ebp) | 第3引数s2を格納する領域 |
20(%ebp) | 第4引数s3を格納する領域 |
まぁ、コンパイラと最適化に依存するとは思うけど。 実際"gcc -O -fomit-frame-pointer"でコンパイルしたコードは以下の通りで、 これだとリターンアドレスが書き変わることもなく、普通に終了。 (exitはgcc的にはnoreturnなので、exit以降のコードが最適化で除去されてしまうというのもあるけど)
_test: subl $1612,%esp addl $16,1604(%esp) addl $1612,%esp ret
アドレス | 説明 |
---|---|
0(%esp) | 自動変数s4を格納する領域 |
1600(%esp) | ? |
1604(%esp) | ? |
1608(%esp) | ? |
1612(%esp) | 関数のリターンアドレスが入ってる |
1616(%esp) | 第1引数s0を格納する領域 |
1620(%esp) | 第2引数s1を格納する領域 |
1624(%esp) | 第3引数s2を格納する領域 |
1628(%esp) | 第4引数s3を格納する領域 |
つーか、アセンブラって難しくて良くわからん。「?」と書いた部分は一体何に使われているのだろう。
λ. 夕食
豊田さんと、あろーむ。
λ. 帰り
に藤沢で思いがけない人物に出会う。驚きと軽い高揚。
スタック領域のアラインメントでは。-mpreferred-stack-boundaryとか。
なるほど。<br>やっぱりアラインメントだったのですか。<br><br>-mpreferred-stack-boundary=2 を指定すると、<br>確かに8バイト境界にアラインされました。<br><br># 実は、最初アラインメントかも知れないとは思ったのですが、<br># 16バイトというのはアラインメントとしては<br># 大きすぎるんじゃないかと思ってしまっていました。