Compiler Construction Lecture 11/1

Compiler Construction Lecture 11/1

先週の復習

先週はさまざまなCPUのレジスタアーキテクチャ(Register architecture) について学んだ。

例えば Intel 386 ならば、

このようなレジスタを持っている。そして、 これ がアセンブラの命令表である。



i386のアセンブラ

i386 は比較的、対称性に欠ける命令体系を持ち、レジスタ も少ない。しかし、可変長の命令を持つので、 コードが若干コンパクトになるという特徴がある。 アドレッシングモードも少ない。

例えば、

     negl %eax    レジスタEAXのnegativeを取る
     negl a       大域変数aのnegative を取る
     negl (%eax)  レジスタEAXの指すメモリのnegativeを取る
     negl (%ebx+%eax) EAX+EBXの指すメモリのnegativeを取る
間接参照には、さらにオフセットを付けることができる
     negl 4(%eax) レジスタEAXの指すメモリから4byteずれたところのnegativeを取る
     negl 4(%ebx+%eax) EAX+EBXの指すメモリから4byteずれたところのnegativeを取る



問題1

i386はlittle-endianであり、メモリにはメモリのアドレス が小さい方に、 数値の小さい桁から格納される。また、%eaxレジスタは、 高い方の桁が8bit %ahレジスタ、低い方の桁が8bit レジスタ%alとなっている。 以下の数値は16進表記とする。

メモリの内容が以下のようになっているとき、

0000100:   23
0000101:   45
0000102:   56
0000103:   78
0000104:   90
0000105:   12
  1. movl 0x100,%eaxは、memory 0x100 の値を%eaxレジスタに格納する。この命令を 実行した時、 %eaxレジスタの値はいくつになるか? %ahレジスタは? %alレジスタは?
  2. movl $0x100,%ebxは、0x100 の値を%ebxレジスタに格納する。
  3. %ebx レジスタが、0x100の時に、movl (%ebx),%eax を実行すると %eax レジスタの値は?
  4. incl %ebx を実行したあとに、movl (%ebx),%eax を実行すると %eax レジスタの値は?
  5. その後、movl 4(%ebx+%eax),%ecx を実行すると %ecx レジスタの値は どのアドレスのメモリからロード(取得)されるか?
  6. movb 2(%ebx),%al を実行すると %eax レジスタの値はどうなるか?
  7. movsbl 2(%ebx),%eax を実行すると %eax レジスタの値はどうなるか?
  8. movsbl 4(%ebx),%eax を実行すると %eax レジスタの値はどうなるか?
  9. leal 8(%ebx+%eax),%ecx を実行すると %ecx レジスタの値は?

さらにgdbの使い方を追求する

BSD/OS の gdb の man ページには、ほとんどなんの記述もない。その 代わりに、info ページが充実している。mule の info か、または、 info コマンドを用いて、GDB の情報を調べてみよ。

gdb には、i386 のレジスタ一覧を表示する機能はない。gdb のaliases 機能を用いて、gdb にその機能を追加するには、

define regs
printf "%%eip=%08x: %%eax=%08x %%ebx=%08x %%ecx=%08x %%edx=%08x %%edi=%08x %%esi=%08x %%ebp=%08x %%esp=%08x\n", $eip,$eax,$ebx,$ecx,$edx,$edi,$esi,$ebp,$esp
end
を.gdbinitに追加する。
stepi
disass $eip $eip+1
は何をするコマンドが調べよ。

アセンブラのシングルステップが便利になるようなaliasを定義してみよ。



アセンブラ(Assembler)を使った計算

i386では、基本的に演算は、register to register で行われる。 ここでは、以下のプログラムを使おう。

int a=4,b=3;
main()
{
    a = a+1-(b-123);
    return a;
}
これを gcc -S でコンパイルしてみると、 .s というファイルに以下の内容がかかれる。(コメントはでないが...)
	.file	"tmp.c"
	.version	"01.01"
gcc2_compiled.:
.globl a
.data
	.align 4
	.type	 a,@object
	.size	 a,4
a:
	.long 4
.globl b
	.align 4
	.type	 b,@object
	.size	 b,4
b:
	.long 3
.text
	.align 4
.globl main
	.type	 main,@function
main:
	pushl %ebp
	movl %esp,%ebp
	movl b,%eax            # 変数bの値を %eax にロードする
	addl $-124,%eax        # -124 を %eax に加算する
	movl a,%edx            # 変数aの値を %edx にロードする
	subl %eax,%edx         # %edx から %eax の内容を引く
	movl %edx,%eax         # %edx の内容を %eax に移す
	movl %eax,a            # %eax の値を変数aに格納(ストア)する
	leave
	ret
.Lfe1:
	.size	 main,.Lfe1-main
	.ident	"GCC: (GNU) 2.8.1"
となる。a: などが大域変数の場所を表している。



宿題1

上のプログラムをIntel CPU上で、gcc -O -S test.c を使って コンパイルすると最適化がかかる。最適化した 場合としない場合で、どのような違いが出るか? (ヒント diff を使うと 簡単...)

問1で、 これらの結果を実際のアセンブラで実行しテストするには、どうすれば良いか 考えて実行せよ。

これらの命令が実際に生成されるCのソースコードを考えて、それをコンパイラ に通し、実際に命令が生成されることを確認せよ。(ただし、データのアドレスは、 変わっても良いとする)

Subject: Report on Compiler consturction Lecture 11/1
というSubjectのメールにして、kono@ie.u-ryukyu.ac.jp まで送ること。 また授業を受けなかったものは、課題を、
Subject: Practice on Compiler consturction Lecture 11/1
というサブジェクトで送ること。 来週の授業(11/8, 11/15)は休講とします。

Kono's home page http://bw-www.ie.u-ryukyu.ac.jp/~kono/