1.1 オートマトンと状態遷移図

5.5 実行時のデータの扱い
(1)機械語におけるデータ表現
①レジスタ
②メモリ
番地付けされたバイトまたはワードの配列
命令の選択によって、整数として、浮動小数点、文字、
ビット等として扱う。
データをどう表現するか、どのように割り付けるかは
コンパイラの役割である。
(2)データ型の内部表現
① 整数、浮動小数点、文字等は計算機ハードウェア表現
を用いる。
② ハードウェアとして用意されていないデータ表現は、
コンパイラで取扱いを定める。
(a)整数
① 通常は1語(計算機によって4バイト、2バイト)
② 負の数は2の補数表現
10
14
-1
-2
0000
0000
1111
1111
0000
0000
1111
1111
0000
0000
1111
1111
1010(000A16)
1110 (000E16)
1111 (FFFF16)
1110 (FFFE16)
・
・
・
-10
-11
1111 1111 1111 0110 (FFFD16)
1111 1111 1111 0101 (FFFC16)
2バイト整数
-32,768 ~ +32,767
整数表現
符号(1ビット)
2の補数(15ビット)
4バイト(32ビット)整数
-2,147,483,648 ~ -2,147,483,647
符号(1ビット)
2の補数(31ビット)
-32,768 (ザン(3)ニー(2)チー(7)ロン(6)パー(8))
-2,147,483,648
(婦人(フヒト(21))のような(47)弱さ(483)虫歯(648)
(b)浮動小数点
計算機別に用意されている表現を用いる。
通常は4バイト。倍長や4倍長がある。
整数
①通常は1語(計算機によって4バイト、2バイト)
②負の数は2の補数表現
【2バイト(16ビット)の場合】
-32,768(= -215)~+32,767(= 215 - 1)
(ザン(3)ニー(2)チー(7)ロン(6)パー(8))
【4バイト(32ビット)の場合】
-2,147,483,648 (= -231)~2,147,483,648 (= 231-1)
(婦人(フヒト(21))のような(47)弱さ(483)虫歯(648)
小数(浮動小数点)2進数表現
浮動小数点数の形式(コンピュータによって異なる)
(注)以下の例は4バイト(32ビット)だが
8バイト(64ビット:倍精度)もある
符号( 1 ビッ
ト)
指数( 7 ビット)
指数仮数(24 ビッ
ト)
符号
: 0のとき非負,1のとき負
指数(n) : 2の補数表現(先頭ビットは符号)
仮数(α): 絶対値 1≦α<1
1
   1,   16 n
16
小数の2進数表現例
たとえば
1 1 0 1
1
0.84375     
2 4 8 16 32
であるから
0 000 0000 1101 1000 0000 0000 0000 0000
16進数で表記すれば,00 D8 00 00
(c)論理値
原理的には1ビットで十分だが、アクセス速度を考え
1バイトか1語で表現される。表現方法は様々。
【Trueの値】
(1バイトの場合)
0000 0001
0000 1111
1000 0000
1111 0000
1111 1111
(1ワードの場合)
0000 0000 0000 0001
0000 0000 0000 1111
1000 0000 0000 0000
1111 0000 0000 0000
1111 1111 1111 1111
8 ビット系 ASCII、EBCDIC
16ビット系 JISコード、シフトJIS
EUC(Extended UNIX Code)
(d)文字
左のテキストファイルを
バイナリファイルとして読み込むと,
以下のようになる
ASCIIコード表
CR:Carriage Return
LF:Line Feed
テキストが
16進数で
表示され
てるね。
なお,
0Dは[CR]
0Fは[LF]
JIS第一水準のコード
0
1
2 3
4
5
6
・・・
82A0 あ ぃ い ぅ う ぇ え ・・・
82B0 げ こ ご さ ざ し じ ・・・
・
・
・
日本語文字は
2byteで表現
するんだ
(e)配列
①同一型のデータの集まり(位置は添え字で指
定)
X[j]
x + s × j
x : X[j]の先頭アドレス
s : Xの1要素のサイズ
②2次元の場合、
X[m, n] (Cの場合 X[m][n])で宣言
X[i,j]
x + s × n × i + s ×
x : X[i, j]の先頭アドレス
s : Xの1要素のサイズ
j
(f)構造体/ユーザ定義型/レコード型
異なるデータの集まり(位置は要素名で指定)
struct { int p; char c, double f;}
【注】
境界合せ(boundary alignment)が必要な場合、
境界をワード、ダブルワードサイズの整数倍に合
わせる必要がある。
境界合せが必要な場合と不要な場合
struct { int p; char c, double f;}
境界合せが不要な場合
境界合せが必要な場合
p
p
c
c
f
f
Ada では、これをソースプログラムで指定可能。
これを表現仕様(representation
specification)という。
(g)文字列
Pascal
文字を要素とする固定長の1次元配列
C
最後尾に値 0 の 1バイトを置く可変長の
文字列。
Prolog
文字のリスト
(h)ポインタ
機械語では番地として扱う。
サイズは機械によって異なる。
基本的には整数と同じで加減算のみが可能。
■昨今の言語では、ポインタの概念を除外
(Java)したり、使う場合は使うことを宣言さ
せることで制限を加える(C#)ことが多い。
(3)変数と一時変数
① ソースプログラム上のデータ(変数や定数)は主記憶上
に割り当てる。
② ただし、命令語中に埋め込むことが可能な小さい整数は、
命令語中のオペランドとして埋め込まれる場合もある。
③ 式の計算途中結果を保存するためにコンパイラが生成す
る一時変数(temporary variable, work variable)は、
主記憶上に割り当てる場合と、レジスタ上に保持するだ
けのものもある。
MC68000での生成法の違い
A = (B + C) * (D - E)
MOV
ADD
MOV
MOV
SUB
MUL
MOV
・
・
・
B, R0
C, R0
R0, Temp
D, R0
E, R0
Temp, R0
R0, A
Temp DA 1
MOV
ADD
MOV
SUB
MUL
MOV
B, R0
C, R0
D, R1 ‘ Tempの替わり
E, R1 ‘ R1を使用
R1, R0
R0, A
(複数の汎用レジスタを使用可能は機械で有
効)
レジスタの使用について
① レジスタの個数には限り(8個、16個など)があるので
ごく少数のデータしか保持できない。
② 主記憶装置よりレジスタのほうがアクセス速度が速い。
③ 各種の演算では、オペランドの一方がレジスタ上にな
ければならないケースがほとんどである。両方のオペラ
ンドが主記憶装置でもよいケースは少ない。
■ 一時変数は記憶装置に割り当て、実行中にレジスタに移
して使うのが基本。
■ レジスタ割り当て(register allocation)は最適化と
して考える。
(4)フレーム
① コンパイラのオブジェクトは、機械語命令の部分とデー
タ部分に分かれる。
② プログラム単位ごとのデータ部分は、以下のように呼ば
れる。
■データフレーム(data frame)
■フレーム(frame)
■起動レコード(activation record)
■データセグメント(data segment)
フレーム内のデータ
①
②
③
④
原始プログラム内に現れる変数や定数のデータ
コンパイラが生成する一時変数や作業用のデータ
呼び出し側の復帰アドレス(return address)
呼出し直前のレジスタの値(register save area)
FORTRANではCOMMONフレームが別に存在する。
再帰的呼び出しが可能な言語では、
これらのデータをスタックに保持し、
リターン時に復帰する必要がある。
(5)再帰的呼び出しのフレーム内データ
再帰的呼び出しが可能な言語では、
フレーム内のデータを関数呼出しごとに
スタックに保持し、
リターン時に復帰する必要がある。
【再帰的呼び出しの例】
fib(int n)
{ int m;
if(n <= 2) m = 1;
else m = fib(n - 2) + fib(n - 1);
return m;
}
再帰的呼び出しのスタック
① 関数呼出し直後のスタックトップには引数の個数分の
呼出し時の実引数(評価済み)が格納されている。
② 実引数をポップアップし、仮引数との対応付けを行う
必要がある。この方法には、
・ディープバインディング(Deep Binding)
・シャドゥバインディング(Shadow Binding)
がある(後述)。通常の言語では Deep Binding が使
われるが、Lisp では Shadow Bindingが使われること
が多い。
③ 上記②のポップアップが行われた後、フレームの保存
が行われる。
(6)ブロック構造
(a)Deep Bindingによる例
Pascal
Procedure A;
Procedure B;
Procedure C;
begin ……… end;
begin ……… end;
Procedure D;
begin ……… end;
begin ……… end;
呼出しが A → B → C → B → D で
実行されたときのフレームのスタック
A
B
変数は、各フレームの
相対番地(offset)で
表現
D
B
C
有効なフレーム
フレームのたどり方
静的リンク(static link)法
ディスプレイ(display)法
(E.W.Dijkstra による)
A
B
D
B
C
有効なフレーム
ディスプレイ
1
2
3
A
B
D
B
C
(b)Shadow Binding
(主としてインタプリタ言語で用いられる。例:LISP)
① 記号表を保持する。
② 呼び出された関数の仮引数名やローカル変数を呼び出
した関数の仮引数名やローカル変数を記号表に登録す
る(仮引数名の場合、引数を評価して値を設定する。
参照渡しの場合は実引数の番地あるいは名前)。
③ 同じ名前が記号表内にあっても重複登録する。
④ 値を取り出したり、設定するときは記号表の最後から
検索する(最も直近で登録された変数が有効となる)。
⑤ 呼び出した関数に戻るとき、仮引数名やローカル変数
を記号表から消す。
(7)ヒープ(heap)領域
■文字列や配列など、不定長のデータに割り当てられ
る領域。
■先に述べたごみ収集処理(GC処理)が必要となる。
■スタックと逆方向に使用領域を確保することが多い。