• 検索結果がありません。

プログラマから見えるCPU 一番下のレベルでコンピュータ上のプログラムがど のように表現されているかを理解する プログラムがどう表現されているか プログラムはコンピュータのメモリ上に載っている コンピュータのメモリには数字しか格納できない したがってプログラムは数字である どう表現されているのか 数

N/A
N/A
Protected

Academic year: 2021

シェア "プログラマから見えるCPU 一番下のレベルでコンピュータ上のプログラムがど のように表現されているかを理解する プログラムがどう表現されているか プログラムはコンピュータのメモリ上に載っている コンピュータのメモリには数字しか格納できない したがってプログラムは数字である どう表現されているのか 数"

Copied!
193
0
0

読み込み中.... (全文を見る)

全文

(1)

計算機学

(2)

プログラマから見える

CPU

一番下のレベルでコンピュータ上のプログラムがど

のように表現されているかを理解する

プログラムがどう表現されているか

プログラムはコンピュータのメモリ上に載っているコンピュータのメモリには数字しか格納できないしたがってプログラムは数字である

どう表現されているのか?

数字で表現された「命令」:機械語CPUごとに異なる

(3)

コンピュータの構成

CPU レジスタ ALU メモリ I/O 周辺機器 キャッシュ バス

(4)

コンピュータの構成

CPU

計算やデータ転送、制 御などを司る ●

ALU

データの算術演算・論 理演算を行う ●

レジスタ

演算・データ転送のた めの数値の一時保存場 所 ●

キャッシュ

メモリとのデータ転送を 高速化 ●

メモリ

データの記憶領域アドレス(番地)で管理

バス

データを転送する経路

I/O

周辺機器との入出力イ

(5)

CPUアーキテクチャ

CPUの設計方針及びインタフェースの総称

命令セットアーキテクチャ ● アドレス空間、データの処理単位の長さ ● 「命令」の種類、機械語と命令の対応 ● レジスタの数や種類 – マイクロアーキテクチャ ● レジスタや演算器(ALU)の論理構成 ● キャッシュの構成や容量 – システムアーキテクチャ ● 各部の実装方式

(6)
(7)

CPUアーキテクチャの種類

CISC (Complex Instruction Set Computer)

1命令が複雑で高度な動作をする

回路は複雑、命令あたりの動作は遅いx86系CPUなど

RISC (Reduced Instruction Set Computer)

1命令は単純な動作

回路は単純、命令あたりの動作は速いARM, MIPSなど

(8)

モデル

CPU

COMET-II (情報処理技術者試験用CPU)

命令記述言語はCASL-IIと呼ばれる16bit CPU (16bit/word)

アドレス空間 64kword (128kbyte)レジスタ構成 ● 8個の汎用レジスタ(GR) ● プログラムレジスタ(PR) ● スタックポインタ(SP) ● フラグ(FR) GR0 (16) GR1 (16) GR2 (16) GR3 (16) GR4 (16) GR5 (16) GR6 (16) SP (16) PR (16) FR (3)

(9)

CPUの動作

1.プログラムレジスタ

(PR)に格納された数値をアドレ

スとみなし、そのアドレスのメモリに格納された数

値を取り出す

2.プログラムレジスタの値を1増やす

3.取り出した数値を「命令」とみなし、解読

4.解読した内容に応じた動作を行う

5.1に戻る

(10)

命令セット

データ転送命令

算術演算・論理演算命令

比較演算命令

シフト演算命令

分岐命令

スタック操作命令

サブルーチン命令

その他

(11)

命令の形式

命令 

[オペランド]

例: LD GR1,#FF00,GR2例: JNZ #001E

オペランド(操作対象)の形式

対象レジスタ1個 POP GR1対象レジスタ2個 LD GR1, GR2数値(アドレス) JUMP #FF00数値とレジスタ LAD GR0, 120数値とレジスタ2個 ST GR0, #FF00, GR1

(12)

アドレッシングモード

例:

LD GRx, 対象

対象の内容をGRxに格納する

LD GR0, GR1

GR0にGR1の内容を格納

LD GR0, #FF00

アドレス FF00(16進)のメモリの内容をGR0に格納

LD GR0, #FF00, GR1

インデックス修飾FF00(16進)にGR1の内容を加えた アドレスの内容をGR0に格納 (右端のレジスタは GR1 GR7のみ)

(13)

データ転送命令

レジスタとレジスタ、レジスタとメモリの間でデータ

を転送する

LD GRx, {GRy | アドレス | アドレス, GRy} ● 対象をGRxに転送 – LAD GRx, {アドレス | アドレス, GRy} ● 対象のアドレスそのものをGRxに格納 ● LAD GR0, #0010 ; GR0に16を格納 – ST GRx, {アドレス | アドレス, Gry} ● GRxの内容を指定したアドレスのメモリに格納

(14)

算術演算・論理演算命令

命令

GRx, 対象

GRxと対象を演算し、結果をGRxに格納

ADDA GRx, 対象 ; 算術加算ADDL GRx, 対象 ; 論理加算SUBA GRx, 対象 ; 算術減算SUBL GRx, 対象 ; 論理減算AND GRx, 対象 ; 論理積OR GRx, 対象 ; 論理和XOR GRx, 対象 ; 排他的論理和

(15)

算術加算と論理加算?

算術加算

/減算は数値を符号付整数とみなす

論理加算

/減算は数値を符号なし整数とみなす

16bit符号なし整数: 0~65535

16bit符号付整数: -32768~32767

違いは何?

符号なし: 32767+1=32768 (問題なし)符号付: 32767+1 = -32768 (オーバーフロー)符号なし: 0-1 = 65535 (アンダーフロー)符号付: 0-1 = -1 (問題なし)

(16)

符号付整数と2の補数表現

nビットで数を表現する

8bit符号なし: 0~2558bit符号付き:-128~127

2の補数による負数の表現

正の数: 00(16)~7F(16) – 負の数: FF(16)~80(16) ● 2の補数表現の利点 – 通常の加減算がそのまま使える最上位ビットを見ると数の正負がわかる 01111111 127 : 00000010 2 00000001 1 00000000 0 11111111 -1 11111110 -2 11111101 -3 : 10000000 -128

(17)

2の補数表現

ある数の「

2の補数」の求め方(すなわち符号の反

転)

まず「1の補数」を求める: 2進表現された数の各桁の 1 と 0 を反転する – 次にその数に1を加える

例: 

-9 を8bit の2の補数表現で表す。

9(10) = 00001001(2) NOT(00001001) = 11110110 11110110 + 1 = 11110111 (答)

(18)

演習

次の式を

8ビット2進数で計算してみよう。

-1+1

3+(-5)

(19)

演算とフラグ

演算結果によってフラグレジスタ

(FR)の内容が

セットされる

FR(3ビット)には OF, SF, ZF (各1ビット)のフラグが含 まれる – OF (Overflow Flag):演算結果がオーバーフローまた はアンダーフローした時1になるSF (Sign Flag): 演算結果が負のとき1になるZF (Zero Flag): 演算結果が0のとき1になる

条件付き分岐命令で参照される

(20)

比較演算命令

減算をして結果のフラグだけをセットする(減算結

果は保存されない)

CPA GRx, 対象

; 算術比較

CPL GRx, 対象

; 論理比較

CPA GR0, GR1 ; GR0-GR1 を計算GR0=GR1なら ZFに1がセットされるGR0<GR1なら SFに1がセットされる

(21)

シフト演算命令

レジスタの各ビットを右か左にずらす

SLA GRx, シフト量 ; 算術左シフト (数値的に2倍)SRA GRx, シフト量 ; 算術右シフト (数値的に1/2倍)SLL GRx, シフト量 ; 論理左シフト (単純なシフト)SRL GRx, シフト量 ; 論理右シフト (単純なシフト) 算術シフト 0 論理シフト 0 0

(22)

シフト演算命令

演算例(

8bit) 本当は16bit

元の数値 SLA SRA SLL SRL 00000101 00001010 00000010 00001010 00000010 11110010 11100100 11111001 11100100 01111001 10001111 10011110 11000111 00011110 01000111 算術シフト 0 論理シフト 0 0

(23)

分岐命令

条件を満たす場合に、指定アドレスから実行

JUMP アドレス ; 指定アドレスから実行するJPL アドレス ; 演算結果が正の場合JMI アドレス ; 演算結果が負の場合JNZ アドレス ; 演算結果が0でない場合JZE アドレス ; 演算結果が0の場合JOV アドレス ; オーバーフローが起きた場合

「条件」はフラグレジスタの状態に対応

正:SF=0 かつ ZF=0 負:SF=1 零:ZF=0 非零:ZF=1

(24)

分岐命令

どうやって実行順序を変えるのか?

実行アドレスは PR レジスタに格納されているPR レジスタに値を格納すれば、次はそのアドレスから 実行が始まる – 分岐命令はレジスタ間のデータ転送命令の一種

(25)

分岐命令の使用例

0000: 1200 0000 LAD GR0,0 ;GR0=0 0002: 1210 0001 LAD GR1,1 ;GR1=1 0004: 1220 0001 LAD GR2,1 ;GR2=1 0006: 1230 000B LAD GR3,11 ;GR3=11 0008: 2401 ADDA GR0,GR1 ;GR0+=GR1 0009: 2412 ADDA GR1,GR2 ;GR1+=GR2 000A: 4413 CPA GR1,GR3 ;GR1-GR3 000B: 6200 0008 JNZ #0008 ;if not zero 0008

(26)

スタック操作命令

スタック:各種データを一時保存しておくメモリ

データをスタックに入れる操作(PUSH)と取り出す操作 (POP)が対になる – 最後に入れたデータが最初に取り出される

PUSH, POP命令

PUSH 値 [, GRy] ● SPレジスタの値を-1し、SPの示すアドレスのメモリに指定し た値(+GRy)を格納する – POP GRy ● SPレジスタの値が示すアドレスのメモリの内容をGRyに格納 し、SPの値を+1する

(27)

PUSHとPOP

10 5 213 FFFF GR0 GR1 GR2 SP FFF8 FFF9 FFFA FFFB FFFC FFFD FFFE FFFF 10 5 213 FFFE 5 10 5 213 FFFD 213 5 10 -53 16 FFFD 213 5 10 -53 213 FFFE 213 5 10 5 213 FFFF 213 5 PUSH 0,GR1 PUSH 0,GR2 途中の処 理でGR1 とGR2の 値が破壊 される POP GR2 POP GR1

(28)

サブルーチン命令

関数やサブルーチンを実現する

→任意のアドレスから特定のアドレスにジャンプ

し、サブルーチン実行後に元のアドレスに戻ってく

CALL アドレス[,GRy] ● 現在実行中のアドレスの次のアドレスをスタックにPUSH ● 指定したアドレスにジャンプ – RET ● スタックからアドレスをPOPして、そのアドレスにジャンプ

(29)

サブルーチン命令

関数やサブルーチンを実現する

→任意のアドレスから特定のアドレスにジャンプ

し、サブルーチン実行後に元のアドレスに戻ってく

CALL アドレス[,GRy] ● 現在実行中のアドレスの次のアドレスをスタックにPUSH ● 指定したアドレスにジャンプ – RET ● スタックからアドレスをPOPして、そのアドレスにジャンプ

(30)

サブルーチン

同じ処理をいろいろなところから利用する

: CALL #2000 : : CALL #2000 : 処理内容 : RET 2000 : CALL #2000 : : CALL #2000 : 処理内容 : RET 2000

(31)

サブルーチンの実現

: CALL #2000 : : CALL #2000 : 処理内容 : RET 2000 1200 1202 1200 FFFF PR SP FFFD FFFE FFFF 2024 : CALL #2000 : : CALL #2000 : 処理内容 : RET 2000 1200 1202 2000 FFFE 1202 PR SP FFFD FFFE FFFF 2024

(32)

サブルーチンの実現

: CALL #2000 : : CALL #2000 : 処理内容 : RET 2000 1200 1202 2024 FFFE 1202 PR SP FFFD FFFE FFFF 2024 : CALL #2000 : : CALL #2000 : 処理内容 : RET 2000 1200 1202 1202 FFFF 1202 PR SP FFFD FFFE FFFF 2024

(33)

その他

SVC アドレス[,GRy]

アドレスを引数としてシステムコール何が起きるかはOS依存OSの機能を呼び出すために使う

NOP

何もしない

(34)

命令コード

それぞれの命令に数値が対応する

命令は1ワード(16bit)または2ワード(32bit)命令語の構成(1ワード目) OP1 (4) OP2 (4) R1 (4) R2 (4) 0: NOP 1: データ転送命令 2: 加減算命令 3: 論理演算命令 4: 比較命令 5: シフト命令 6: 分岐命令 7: スタック操作命令 8: サブルーチン命令 F: SVC

(35)

命令コード

算術演算の場合の例

OP1 OP2 R1,R2 命令長 命令 2 0 0~7 2 ADDA R1, addr, R2 1 0~7 2 SUBA R1, addr, R2 2 0~7 2 ADDL R1, addr, R2 3 0~7 2 SUBL R1, addr, R2 4 0~7 1 ADDA R1, R2 5 0~7 1 SUBA R1, R2 6 0~7 1 ADDL R1, R2 7 0~7 1 SUBL R1, R2 ADDL GR0, #FF00, GR3 2203 FF00 SUBA GR2, GR4 2524 ADDA GR2, #1234 2020 1234

(36)

プログラム例

GR1とGR2に入っている整数の乗算サブルーチン

GR2≧0を仮定結果はGR0に格納GR3の内容は破壊される 0000: 1200 0000 LAD GR0,0 ;GR0←0 0002: 1230 0001 LAD GR3,1 ;GR3←1 0004: 2401 ADDA GR0,GR1 ;GR0←GR0+GR1 0005: 2723 SUBL GR2,GR3 ;GR2←GR2-GR3

0006: 6200 0004 JNZ #0004 ;if not zero goto 0004 0008: 8100 RET ;return

(37)

プログラム例

GR1とGR2に入っている整数の乗算サブルーチン

GR2,GR3を破壊しないバージョン 0000: 1200 0000 LAD GR0,0 ;GR0←0 0002: 7002 0000 PUSH 0,GR2 ;GR2を退避 0004: 7003 0000 PUSH 0,GR3 ;GR3を退避 0006: 1230 0001 LAD GR3,1 ;GR3←0 0008: 2401 ADDA GR0,GR1 ;GR0←GR0+GR1 0009: 2723 SUBL GR2,GR3 ;GR2←GR2-GR3

000A: 6200 0008 JNZ #0008 ;if(not zero) goto #0008 000C: 7130 POP GR3 ;GR3を復帰

000D: 7120 POP GR2 ;GR2を復帰 000E: 8100 RET ;return

(38)

演習

これは何をするプログラムか説明せよ。

入力は GR1(アドレス)、GR2(正の整数)出力は GR3(整数)0011番地の 1 は定数 0000: 1031 0000 LD GR3,0,GR1 0002: 2210 0011 ADDL GR1,#0011 0004: 2320 0011 SUBL GR2,#0011 0006: 6300 0010 JZE #0010 0008: 4031 0000 CPA GR3,0,GR1 000A: 6500 0002 JPL #0002 000C: 1031 0000 LD GR3,0,GR1 000E: 6400 0002 JUMP #0002 0010: 8100 RET

(39)

機械語とニモニック

計算機は機械語(数字で表される命令列)で動く

12000000700200007003000012300001240127236 2000008713071208100 ●

これではわかりにくいので、命令を表現する記号

(ニモニック、

mnemonic)でプログラムを書く

動作との対応がつけやすい機械語とニモニックは1対1対応機械語列にするには変換が必要 LAD GR0,0 LAD GR3,1 ADDA GR0,GR1 SUBL GR2,GR3 JNZ #0004 RET Mnemonic: 記憶術

(40)

アセンブリ言語

ニモニックから機械語への変換:アセンブル(組立)

表参照と簡単なルールで変換できる

もっと便利に:アセンブリ言語

疑似命令 ● プログラム開始・終了の宣言 ● 定数領域・データ領域の宣言 – ラベル ● ジャンプ先やデータのアドレスを自動計算 – マクロ ● よく使う命令列を1行で表現する

機械語への変換は

アセンブラ

が行う

(41)

アセンブリ言語の例

; GR1とGR2の掛け算

MULT

START

LAD GR0,0

LOOP

ADDA GR0,GR1

SUBL GR2,

ONE

JNZ

LOOP

RET

ONE

DC

1

END

ラベル 疑似命令 コメント

(42)

アセンブリ言語

疑似命令

命令と同じ形式で記述されるが、命令そのものではな い – START: プログラムの最初を指定する(ラベル必須)END: プログラムの終わりを指定するDC: 定数を定義する メモリ上にその数字が格納されるが、命令ではない – DS: データ領域を定義する メモリ上に指定した語数の領域が確保される。 データ処理などに使う用途

(43)

アセンブリ言語

ラベル

プログラム内のアドレスやデータのアドレスを記号で参 照する ● 実際のアドレスへの変換はアセンブラが行う ● 命令を挿入・削除した時にも変更しなくてよい ●

マクロ

よく使う複数の命令列を1つの命令のように書ける ● IN アドレス,長さ 指定したメモリにデータを入力 ● OUT アドレス,長さ 指定したメモリの内容を出力 ● RPUSH 全レジスタをPUSH ● RPOP 全レジスタをPOP

(44)

アセンブリ言語

定数の記述

定数は演算などに頻繁に使うので、あたかも定数を直 接演算できるかのように書ける MULT START LAD GR0,0 LOOP ADDA GR0,GR1 SUBL GR2,=1 JNZ LOOP RET END MULT START LAD GR0,0 LOOP ADDA GR0,GR1 SUBL GR2,CONST1 JNZ LOOP RET CONST1 DC 1 END 自動 生成

(45)

アセンブラによる処理

アセンブリ言語 のプログラム アセンブラ のプログラム機械語 リンカ ライブラリ 実行可能 プログラム

(46)

演習

● アセンブリ言語を使い、下記のプログラムをわかりやすく記述せよ。 – 疑似命令: START, ENDラベル定数演算 0000: 1031 0000 LD GR3,0,GR1 0002: 2210 0011 ADDL GR1,#0011 0004: 2320 0011 SUBL GR2,#0011 0006: 6300 0010 JZE #0010 0008: 4031 0000 CPA GR3,0,GR1 000A: 6500 0002 JPL #0002 000C: 1031 0000 LD GR3,0,GR1 000E: 6400 0002 JUMP #0002 0010: 8100 RET

(47)

アセンブリ言語によるプログラミング

CASL-IIを使ってさまざまなプログラムを書いてみ

通常は高級言語(Cなど)で書く操作をアセンブラで書い たらどうなるか – コンピュータの基本的な動きを理解する

(48)

高速な乗算

加算を繰り返す乗算は簡単だが効率が悪い

a×b=(a+a+...+a) aをb回加算

筆算の要領で計算する

乗算の値によらず、桁数に比例する計算で済む 00101010 X 01101000 ---00101010 00101010 00101010 ---01000100010000 42 X 104 ---168 42 4368

(49)

高速な乗算

アルゴリズム(

Z←A×B)

Z←0 For i=16 to 1 by -1 If Bの最下位ビットが1 then Z←Z+A End if A←A*2 B←B/2 End for 00101010 X 01101000 ---00101010 00101010 00101010 ---01000100010000

(50)

高速な乗算

i A B Z 1 00101010 01101000 0 2 001010100 0110100 0 3 0010101000 011010 0 4 00101010000 01101 00101010000 5 001010100000 0110 00101010000 6 0010101000000 011 0011010010000 7 00101010000000 01 001000100010000 8 001010100000000 0 001000100010000

(51)

注意点

GR2の下1ビットを取り出す

AND GR2,=1これを実行するとGR2の内容が破壊されるGR2の内容を保存したい場合は別なレジスタを使うLD GR4,GR2AND GR4,=1

GR1の値を2倍する

SLA GR1,1 ; 1ビット算術左シフト

GR2の値を1/2倍する

SRA GR2,1 ; 1ビット算術右シフト

(52)

アセンブリ言語で書いてみる

Z: GR0, A: GR1, B: GR2, i: GR3 とする

FMULT START LAD GR0,0 ; GR0←0 LAD GR3,16 ; GR3←16 LOOP LD GR4,GR2 ; G4←G2 AND GR4,=1 ; G4←G4 and 1

JZE SKIP1 ; if not zero then

ADDA GR0,GR1 ; G0←G0+G1

SKIP1 SLA GR1,1 ; G1←G1*2

SRA GR2,1 ; G2←G2/2

SUB GR3,=1 ; G3←G3-1

JNZ LOOP ; if not zero goto LOOP

RET ; return

(53)

再帰呼び出しによる計算

C言語でよくあるやつ

int factorial(int n) { if (n == 0) return 1 return n*factorial(n-1) } ●

さっきの

FMULTを使ってみる

FMULTはGR1,GR2を入力としてGR0を出力とする GR4を破壊する

(54)

再帰呼び出しによる計算

GR5を入力、GR0を出力とする

基本的な考え方

GR5が0ならGR0に1を代入して終了GR5を退避GR5を1減らして階乗を計算→GR0GR5を復帰GR5とGR0の積をGR0に代入して終了

(55)

プログラム

FACT START

CPA GR5,=0 ; GR5-0

JNZ SKIP2 ; if zero then LAD G0,1 ; GR0←1 RET ; return SKIP2 PUSH 0,GR5 ; GR5を保存 SUBA GR5,=1 ; GR5←GR5-1 CALL FACT ; GR0←GR5の階乗 LD GR1,GR0 ; GR1←GR0 POP GR5 ; GR5を復帰 LD GR2,GR5 ; GR2←GR5 CALL FMULT ; GR0←GT1*GR2 RET ; return END

(56)

メモリの内容の探索

GR1から始まるGR2個のメモリの中にGR3の内容

があるかどうかをチェック

存在する場合には

GR0にアドレスを返す

存在しない場合には

GR0に0を返す

アドレス 値 8000 23 8001 5 8002 323 8003 532 8004 34 8005 322 8006 167 GR1=#8000,GR2=7,GR3=34 →GR0=#8004 GR1=#8000,GR2=4,GR3=34 →GR0=0 GR1=#8000,GR2=7,GR3=322 →GR0=8005

(57)

アルゴリズム

While GR2 > 0

If M[GR1] = GR3 then

GR0←GR1

Return

End if

GR2←GR2-1; GR1←GR1+1

End while

GR0←0

return

(58)

プログラム

SEARCH START

LOOP CPL GR2,=0 ; GR2-0

JNZ SKIP1 ; if zero then JUMP BREAK ; goto BREAK SKIP1 CPA GR3,0,GR1 ; GR3-M[GR1]

JNZ SKIP2 ; if zero then LD GR0,GR1 ; GR0←GR1

RET ; return

SKIP2 ADDL GR1,=1 ; GR1←GR1+1 SUBL GR2,=1 ; GR2←GR2-1 JUMP LOOP ; goto LOOP BREAK LAD GR0,0 ; GR0←0

RET ; return

(59)

演習

メモリ領域をコピーするプログラムを書け。

GR0が指すアドレスからGR2の個数分のメモリをGR1 が指すアドレス移行にコピーする。 – GR0~GR0+GR2の領域とGR1~GR1+GR2の領域 には重なりがないものとする。 – アドレス 内容 アドレス 内容 8000 48 8100 00 8001 65 8101 00 8002 6C 8102 00 8003 6C 8103 00 8004 6F 8104 00 8005 2C 8105 00 8006 77 8106 00 8007 6F 8107 00 8008 72 8108 00 GR0=#8000 GR1=#8100 GR2=5 でプログラム起動⇒

(60)

演習

メモリ領域をコピーするプログラムを書け。

GR0が指すアドレスからGR2の個数分のメモリをGR1 が指すアドレス移行にコピーする。 – GR0~GR0+GR2の領域とGR1~GR1+GR2の領域 には重なりがないものとする。 – アドレス 内容 アドレス 内容 8000 48 8100 48 8001 65 8101 65 8002 6C 8102 6C 8003 6C 8103 6C 8004 6F 8104 6F 8005 2C 8105 00 8006 77 8106 00 8007 6F 8107 00 GR0=#8000 GR1=#8100 GR2=5 でプログラム起動⇒

(61)

演習の方針

(必ずしもこの通りでなくてもよい)

1.GR0の指すメモリの内容をGR3にコピー (LD)

2.GR3の内容をGR1の指すメモリにコピー (ST)

3.GR0に1を加える (ADDL)

4.GR1に1を加える (ADDL)

5.GR2から1を引く (SUBL)

6.0でなければ1.へ (JNZ)

7.RET

(62)

高級言語

アセンブリ言語の問題点

実現したい計算とCPUの機能が違う →複数の命令の組み合わせで1つの処理をする →わかりにくい – CPUによって命令が異なる →ある計算機のプログラムをほかの計算機で使えない ●

高級言語

「計算したい内容」を直接記述→自動的に機械語に変 換 – 人間にとって記述が容易変換プログラムをCPUごとに書けば、高級言語のプロ

(63)

初期の高級言語

FORTRAN (1955)

数値計算言語計算を数式で記述できる(FORmula TRANslator)装置と直接対応する入出力(プリンタ、カードリーダ、 キーボード、磁気テープなど) – GOTO文による実行制御

LISP (1958)

記号とその並び(リスト)を処理する(LISt Processor)関数型言語、括弧()を使った記述今なお使われる柔軟性

(64)

初期の高級言語

COBOL (1959)

ビジネス処理用言語

(COmmon Business Oriented Language)

表の入出力と集計(現在の表計算処理に近い)読みやすさ重視

● プログラムの説明文が言語仕様に含まれる ● 自然言語に近い命令文

(65)

いろいろなプログラム言語

ユークリッドの互除法を実装してみる

GCD(m,n):

If (n=0) then m

Else GCD(n,m mod n)

GCD(m,n):

while (n≠0)

t←n

n←m mod n

m←t

End while

Return m

(66)

Fortran (1954)

下のコードは

Fortran 66 (1966)

M=100 N=72 10 IF (N) 20,30,20 20 CONTINUE I=N N=M-INT(REAL(M)/REAL(N))*N M=I GOTO 10 30 WRITE(6,40) M 40 FORMAT(1H ,I5) STOP END

(67)

Fortran (1954)

下のコードは

Fortran 95 (1995)

program GCD integer::euclid_gcd integer::m,n m = 100 n = 72 Print *, euclid_gcd(m,n) end program

integer function euclid_gcd(m,n) integer::m,n integer::t do while (n /= 0) t = n n = mod(m,n) m = t end do gcd = m return end function

(68)

LISP (1958)

コードは

Common Lisp (1984)

(defun euclid-gcd (m n)

(if (= n 0) m

(euclid-gcd n (mod m n))

)

)

(print (euclid-gcd 100 72))

(69)

COBOL (1959)

IDENTIFICATION DIVISION.

PROGRAM-ID. EUCLID-GCD. AUTHOR. AKINORI ITO.

DATE-WRITTEN. 2018/6/10. DATE-COMPILED. 2018/6/10. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. WORKING-STORAGE SECTION. 01 M PICTURE 99999. 01 N PICTURE 99999. 01 T PICTURE 99999. 01 X PICTURE 99999. PROCEDURE DIVISION. MOVE 100 TO M. MOVE 72 TO N. PERFORM UNTIL N = 0 MOVE N to T

DIVIDE M BY N GIVING X REMAINDER N MOVE T to M

END-PERFORM. DISPLAY M.

(70)

BASIC(1964)

下のコードは

Chipmunk Basic (1990)

10 m=100:n=72

20 if n<>0 then goto 40

30 print m:end

40 t=n: n=m mod n: m=t

50 goto 20

(71)

Pascal (1970)

Program GCD(output);

function euclid_gcd(m:integer; n:integer):integer; var t:integer; begin if n=0 then euclid_gcd := m else begin t := euclid_gcd(n, m mod n); euclid_gcd := t end end; begin writeln(euclid_gcd(100,72)); end.

(72)

C (1972)

下のコードは

ANSI-C (1990)

#include <stdio.h>

int euclid_gcd(int m, int n) { if (n == 0) return m; return euclid_gcd(n, m%n); } int main() { printf("%d\n",euclid_gcd(100,72)); return 0; }

(73)

C++ (1983)

#include <iostream> using namespace std;

int euclid_gcd(int m, int n) { if (n == 0) return m;

return euclid_gcd(n, m%n); }

int main() {

cout << euclid_gcd(100,72) << endl; return 0;

(74)

Perl (1987)

sub euclid_gcd { my ($m, $n) = @_; if ($n == 0) { return $m; } return euclid_gcd($n, $m%$n); } print euclid_gcd(100,72);

(75)

Tcl (1988)

proc euclid_gcd {m n} { if {$n == 0} {

return $m } else {

return [euclid_gcd $n [expr $m%$n]] }

}

(76)

Haskell (1990)

euclid_gcd m 0 = m

euclid_gcd m n = euclid_gcd n (m `mod` n) main = print (euclid_gcd 100 72)

(77)

Python (1991)

def euclid_gcd(m,n):

if n==0:

return m

return euclid_gcd(n,m%n)

print(euclid_gcd(100,72))

(78)

Ruby (1993)

def euclid_gcd(m,n) if n==0 then return m else return euclid_gcd(n,m%n) end end print euclid_gcd(100,72),"\n"

(79)

Lua (1993)

function euclid_gcd(m,n)

if n==0 then

return m

else

return euclid_gcd(n,m%n)

end

end

print(euclid_gcd(100,72))

(80)

Java (1995)

public class Main {

public static int euclid_gcd(int m, int n) { if (n == 0) return m;

return euclid_gcd(n,m%n); }

public static void main(String []args){

System.out.println(euclid_gcd(100,72)); }

(81)

JavaScript (1995)

function euclid_gcd(m,n) { if (n == 0) { return m; } return euclid_gcd(n,m%n); } console.log(euclid_gcd(100,72));

(82)

R (1996)

euclid.gcd <- function(m,n) {

if (n==0) {

return(m)

}

return(euclid.gcd(n,m%%n))

}

cat(euclid.gcd(100,72))

(83)

C# (2000)

using System.IO; using System;

class Program {

static int Euclid_GCD(int m, int n) { if (n==0) return m;

return Euclid_GCD(n,m%n); }

static void Main() {

Console.WriteLine(Euclid_GCD(100,72)); }

(84)

Go (2009)

package main import "fmt"

func euclid_gcd(m int, n int) int { if (n==0) { return m } return euclid_gcd(n,m%n) } func main() { fmt.Printf("%d\n",euclid_gcd(100,72)) }

(85)

Julia (2012)

function euclid_gcd(m,n)

if n==0

m

else

euclid_gcd(n,m%n)

end

end

println(euclid_gcd(100,72))

(86)

高級言語の実現方式

コンパイラ

高級言語のプログラムを読み込み、それを機械語に変 換して、単独で動く機械語の実行形式ファイルを生成す る – 実行は高速、できたプログラムはCPU依存デバッグが面倒(動いているプログラムとソースプログ ラムの対応がつけにくい) ソース プログラム コンパイラ オブジェクト プログラム (機械語) リンカ ライブラリ 実行可能 プログラム

(87)

高級言語の実現方法

インタプリタ

高級言語のプログラムを読み込み、その内容を直接実 行する (高級言語に対応する機械語のプログラムは生成され ない) – 実行は遅く、プログラムのCPU依存性は少ない実行状況が把握しやすい ソース プログラム インタプリタ 直接 実行

(88)

高級言語の実現方法

中間言語(バイトコード)コンパイラ

仮想的なCPUの機械語にコンパイル→CPUエミュレー タ(仮想マシン、VM)による実行実行する計算機のCPUに依存せず、インタプリタより速 い(コンパイラより遅い) ソース プログラム コンパイラ オブジェクト プログラム (機械語) バイトコード エミュレータ (仮想マシン) 直接 実行

(89)

代表的な高級言語と実現方法

コンパイラ

インタプリタ

中間言語

Fortran LISP* C C++ Objective-C LISP* BASIC Perl Ruby Python* JavaScript PHP Smalltalk Java Python* C#

(90)

コンパイラのお仕事

ソースプログラムから最終的な機械語(コード)を生

成するには段階がある

ソース プログラム 中間表現 コード 最適化コード 構文解析・ 変換ルール コード生成 ルール 最適化 ルール

(91)

構文解析

単なる文字列であるソースプログラムから構造を

見つけ出す

a=b+1;

プログラム 文 変数 = 式 ; a + 変数 b 定数 1

構文木

(92)

構文解析ルールの例

プログラム:文

プログラム:プログラム 文

文:変数

= 式;

式:変数

式:定数

式:式

+ 式

式:式 – 式

式:

(式)

(93)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(94)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(95)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(96)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(97)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(98)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(99)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(100)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(101)

構文解析ルールと構文木

● プログラム:文 ● プログラム:プログラム 文 ● 文:変数 = 式; ● 式:変数 ● 式:定数 ● 式:式 + 式 ● 式:式 – 式 ● 式:(式) プログラム 文 変数 = 式 ; a + 変数 b 定数 1 構文木が1段下がる部分は構文解析ルール1つと対応する

(102)

演習

次のプログラムの構文木を示せ。

(103)

構文木から中間表現へ

さまざまな中間表現がある

ここでは「四つ組」を紹介

四つ組:(演算 対象1 対象2 格納先)

元の文 四つ組 y=x+1 (+, x, 1, y) z=x+y+2 (+, x, y, T1) (+, T1, 2, z) x=a+b*c (*, b, c, T1) (+, a, T1, x) x=1 (=, 1, ,x) T1は中間変数 (自動的に確保される) 必要に応じてT2, T3 なども 使う

(104)

構文木から中間表現へ

機械的な四つ組生成

「変数=式;」の場合、 ● 式の四つ組を生成 ● 値が格納された中間変数をTと するとき、(=, T, ,変数) を生成 – 「式1+式2」の場合、 ● 式1の四つ組を生成し、中間変 数T1に格納 ● 式2の四つ組を生成し、中間変 数T2に格納 ● 自動生成された中間変数をTと するとき、(+, T1, T2, T) を生成 文 変数 = 式 ; a + 変数 b 定数 1

(105)

構文木から中間表現へ

機械的な四つ組生成

「変数」の場合、 ● 中間変数をTとすると (=, 変数, ,T) を生成 – 「定数」の場合、 ● 中間変数をTとすると (=, 定数, ,T) を生成 文 変数 = 式 ; a + 変数 b 定数 1

(106)

構文木から中間表現へ

生成例

文 変数 = 式 ; a + 変数 b 定数 1

(107)

構文木から中間表現へ

生成例

式の部分の四つ組を生成 してT1に格納T1を変数に格納 文 変数 = 式 ; a + 変数 b 定数 1

(108)

構文木から中間表現へ

生成例

式の部分の四つ組を生成 してT1に格納(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(109)

構文木から中間表現へ

生成例

左の式の四つ組を生成してT2 に格納 – 右の式の四つ組を生成してT3 に格納 – (+, T2, T3, T1)(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(110)

構文木から中間表現へ

生成例

変数の内容をT2に格納右の式の四つ組を生成してT3 に格納 – (+, T2, T3, T1)(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(111)

構文木から中間表現へ

生成例

(=, b, ,T2)右の式の四つ組を生成してT3 に格納 – (+, T2, T3, T1)(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(112)

構文木から中間表現へ

生成例

(=, b, ,T2)定数をT3に格納(+, T2, T3, T1)(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(113)

構文木から中間表現へ

生成例

(=, b, ,T2)(=, 1, ,T3)(+, T2, T3, T1)(=, T1, ,a) 文 変数 = 式 ; a + 変数 b 定数 1

(114)

構文木から

4つ組の生成

文 変数 = 式 ; a + 変数 b 定数 1 ●

準備

構文木の節点(ノード) Node n; – 節点の子節点 n.child(k) – 節点の種類 n.type == “文”

(115)

構文木から

4つ組の生成

文 変数 = 式 ; a + 変数 b 定数 1 ●

準備

構文木の節点(ノード) Node n; – 節点の子節点 n.child(k) – 節点の種類 n.type == “文”

(116)

構文解析ルールの例

プログラム:文

プログラム:プログラム 文

文:変数

= 式;

式:変数

式:定数

式:式

+ 式

式:式 – 式

(117)

4つ組生成手続き(文)

Generate(Node n) {

If (n.type == “式” and

n.child.type == (“変数” “=” “式” “;”)) { tmpvar = 一時変数名

GenerateExpression(n.child(2), tmpvar) Output(“=”, tmpvar, null, n.child(0))

} }

(118)

4つ組生成手続き(式)

GenerateExpression

(Node n, String tmpvar) {

If

(n.child(0).typeが “変数” または “定数”) {

Output

(“=”,n.child(0).child(0), null,tmpvar)

}

Else if

(n.child(1).type が “+” または “-”) {

t1 = 一時変数名; t2 = 一時変数名

GenerateExpression

(n.child(0), t1)

GenerateExpression

(n.child(2), t2)

Output

(n.child(1).type, t1, t2, tmpvar)

}

(119)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13

(120)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n.child(2), tmpvar)

Output(“=”, tmpvar, null, n.child(0)) n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(121)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1")

Output(“=”, tmpvar, null, n.child(0)) n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(122)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") GenerateExpression(n.child(2), "T3") Output(n8.type, "T2", "T3", "T1")

Output(“=”, "T1", null, n.child(0))

n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(123)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") GenerateExpression(n.child(2), "T3") Output(n8.type, "T2", "T3", "T1")

Output(“=”, "T1", null, n.child(0))

n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(124)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n.child(0).child(0), null,"T2") GenerateExpression(n.child(2), "T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(125)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n.child(2), "T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1

n2 n3 n4 n5

n6 n7 n8 n9

n10 n11

(126)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n.child(2), "T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2)

(127)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2)

(128)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2)

(129)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2)

(130)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output(n.child(1).type, "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2) (=, 1, , T3)

(131)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output(n.child(1).type, "T2", "T3", "T1")

Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2) (=, 1, , T3)

(132)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output("+", "T2", "T3", "T1")

Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2) (=, 1, , T3) (+, T2, T3, T1)

(133)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output("+", "T2", "T3", "T1") Output(“=”, "T1", null, n.child(0))

n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2) (=, 1, , T3) (+, T2, T3, T1)

(134)

4つ組の生成例

文 変数 = 式 ; a + 変数 b 定数 1 Generate(n1) GenerateExpression(n4, "T1") GenerateExpression(n7, "T2") Output(“=”,n12, null,"T2") GenerateExpression(n9, "T3") Output(“=”,n13, null,"T3") Output("+", "T2", "T3", "T1") Output(“=”, "T1", null, a) n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 (=, b, , T2) (=, 1, , T3) (+, T2, T3, T1) (=, T1, ,a)

(135)

効率の良い中間表現生成

前ページの中間表現は実は

1行で書ける

(+, b, 1, a)最初からこういう中間表現を生成するには?中間表現の生成ルールを細かくする中間表現を生成した後、コードの無駄を省く処理を行う (最適化)

(136)

細かいコード生成ルール

「式

1+式2」の場合

最後に格納する一時変数をT1とする1の先 変数 定数 その他 式2の 先 変数 (+,変数1,変数2,  T1) (+,定数1,変数2, T1) 式1の四つ組を生成し てT2に格納 (+,T2,変数2,T1) 定数 (+,変数1,定数2,  T1) (+,定数1,定数2, T1) 式1の四つ組を生成し てT2に格納 (+,T2,定数2,T1) その他 式1の四つ組を生成 してT2に格納 (+,T2,変数2,T1) 式1の四つ組を生成 してT2に格納 (+,T2,定数2,T1) 式1の四つ組を生成し てT2に格納 式2の四つ組を生成し てT3に格納 (+,T2,T3,T1)

(137)

最適化の例

中間表現があるパターンに合致する場合には置き換

えを行う

例:ある一時変数に何かを代入し、そのあとその一時変数1回しか使われていなければ、後者の一時変数を前者 の変数または定数に置き換える。 – ある一時変数に結果を代入し、それをすぐに別な変数に 代入しているとき、一時変数をその変数に置き換える。 (=, x, ,T3) : (+, T3, T4, T2) (=, x, ,T3) : (+, x, T4, T2) (+, x, y, T1) (=, T1, , z) (+, x, y, (=, T1, ,z)z)

(138)

最適化の例

(=, b, ,T2) (=, 1, ,T3) (+, T2, T3, T1) (=, T1, ,a) (=, b, ,T2) (=, 1, ,T3) (+, b, T3, T1) (=, T1, ,a) (=, 1, ,T3) (+, b, T3, T1) (=, T1, ,a) (=, 1, ,T3) (+, b, 1, T1)

(139)

コード生成

四つ組の列を命令列に変換

変換ルール例

四つ組

ニモニック

(=, X, , Y) LD G0,X ST G0,Y (+, X, Y, Z) LD G0,X ADDA G0,Y ST G0,Z (-, X, Y, Z) LD G0,X SUBA G0,Y ST G0,Z

(140)

コード生成例

高級言語 中間言語 生成コード

X=Y+1; (+,Y, 1, X) LD G0,Y

ADDA G0,=1 ST G0,X Z=X+Y-2; (+, X, Y, T1) (-, T1, 2, Z) LD G0, XADDA G0, Y ST G0, T1 LD G0, T1 SUBA G0, =2 ST G0, Z

(141)

演習

Z=X+Y-2 からコード生成が行われるまでの処理を

記述せよ。

構文木四つ組の生成最適化コード生成

(142)

データ表現とデータ構造

コンピュータは数字しか扱えない

メモリの1つの番地には一定範囲の整数しか格納でき ない – 8ビットなら0~255,または-128~127

それ以外のデータはどうやって表現されているの

か?

実数文字と文字列マルチメディアデータ(画像,音声)

(143)

整数

符号なし

nビット整数 0~2

n

-1

符号付き

nビット整数 -2

n-1

2

n-1

-1

ビット長 符号なし 符号付き 8 (char) 0~255 -128~127 16 (short) 0~65535 -32768~32767 32 (long) 0~4294967295 -2147483648~ 2147483647 64 (long long) 0~18446744073709551 615 -9223372036854775808~ 9223372036854775807

(144)

実数

固定小数、有理数、浮動小数

固定小数:小数点の上と下の精度が固定有理数:整数の比 ● 数式処理などでは使われるが、あまり一般的でない – 浮動小数:小数点の位置が変動 ● 6.0221413×1023のような形式 ●

多くの場合浮動小数形式が使われる

(145)

固定小数表現

小数点の上と下の精度が固定

– 32ビット固定小数 -8000.0000~7FFF.FFFF16 10進では-32768.0~32767.9999847412109375 – 最小精度 0.000116=0.000015258789062510

利点:計算が簡単

基本的に通常の整数演算と同じ

欠点:表せる数値の範囲が限られる

限られた範囲の数だけを高速に表現する用途に使

われる

信号処理チップなど

(146)

浮動小数表現

数値の有効桁数を一定にする表現方法

6.0221413×1023のような形式 – 符号s×仮数a×基数b指数pの形式で表される通常1≤a<2, b=2, s=1 or -1 s p a ビット長 s p a 有効桁 数 32 (float) 1 8 23 7.22 64 (double) 1 11 52 15.95 128 1 15 112 34.02

(147)

IEEE形式浮動小数

16, 32, 64, 128bit

s=0 (正の数)またはs=1(負の数)

指数部はバイアス表現

-2n-1+2~2n-1-1を表現、整数の2n-1-1を0とする ● 表したい数値に2n-1-1を加える – 8ビットの場合、0116が-126, 7F16が0,FE16が127 ●

「数でないもの」の表現

– オーバーフローを表す +Inf, -Inf (p=FF16, a=0) – Not a Number (NaN) (p=FF16, a≠0)

(148)

IEEE形式浮動小数

例:

-3.5をIEEE形式32ビット浮動小数にする

負の数なのでs=1 – 3.5=7.0×2-1 より、3.5=1112×2-1=11.12 – 11.12=11.12×20=1.112×21より、a=1.112, p=1 – pをバイアス表現にし(127を加え)て2進数にすると ● p=10000000 2 – sが1ビットpが8ビットaが23ビット(aの先頭の1.を除く)1100 0000 0110 0000 0000 0000 0000 0000

(149)

演習

4.125をIEEE形式32ビット浮動小数で表せ。

a) 符号sを決める b) 4.125を小数点付き2進数に変換する。 c) それを1以上2未満の数a×2pの形にする。 d) pを8ビットのバイアス表現に変換。 e) s(1ビット)、p(8ビット)、a(23ビット)を並べる。 a) aの先頭の1.は省く b) 23ビットに満たない部分は右に0を詰める

(150)

浮動小数演算

浮動小数の形式に合わせるため、複雑な計算が

必要

x1=(s1,a1,p1)とx2=(s2,a2,p2)の加算

(簡単のためs1=s2、p1>p2と仮定する)

a2←a2/2

p1-p2

a←a1+a2, p←p1, s←s1

while a>2

a←a/2, p←p+1

return (s,a,p)

(151)

浮動小数演算

x1=(s1,a1,p1)とx2=(s2,a2,p2)の乗算

  

s←s1×s2

p←p1+p2

a←a1×a2

while a>2

a←a/2, p←p+1

return (s,a,p)

(152)

文字の表現

整数と文字を対応させる(符号化)

文字セット(文字集合):表現すべき文字の集合

言語に依存する多くの言語が同時に表現できる文字セットもある

文字コード(文字符号):文字セット内の文字と数字

の対応(またはその数字)

1つの文字セットに対して文字コードが複数ある場合も ある

(153)

文字セット

表現すべき文字の集合

英語

US-ASCII: アルファベット、数字、記号

日本語

JIS X0201: アルファベット+記号・数字+カタカナ(い わゆる半角カナ) – JIS X0208: 漢字+記号(いわゆる全角記号)JIS X0213: 補助漢字

多言語

(154)

US-ASCII

英語のための代表的な文字セット・文字コード

American Standard Code for Information

Interchange の略

(155)

US-ASCII

20 sp 30 0 40 @ 50 P 60 ` 70 p 21 ! 31 1 41 A 51 Q 61 a 71 q 22 “ 32 2 42 B 52 R 62 b 72 r 23 # 33 3 43 C 53 S 63 c 73 s 24 $ 34 4 44 D 54 T 64 d 74 t 25 % 35 5 45 E 55 U 65 e 75 u 26 & 36 6 46 F 56 V 66 f 76 v 27 ' 37 7 47 G 57 W 67 g 77 w 28 ( 38 8 48 H 58 X 68 h 78 x 29 ) 39 9 49 I 59 Y 69 i 79 y 2A * 3A : 4A J 5A Z 6A j 7A z 2B + 3B ; 4B K 5B [ 6B k 7B { 2C , 3C < 4C L 5C \ 6C l 7C | 2D - 3D = 4D M 5D ] 6D m 7D } 2E . 3E > 4E N 5E ^ 6E n 7E ~ 2F / 3F ? 4F O 5F _ 6F o 7F DEL

(156)

文字コード(文字符号化方式)

文字セット中の文字には番号が振られているが、

それをどうやってコンピュータ上で表現するかは別

途規定される(文字符号化方式)

日本語の場合

文字セット:JIS X0201+X0208+X0213文字コード ● ISO-2022-JP ● Shift-JIS ● EUC-JP

参照

関連したドキュメント

つの表が報告されているが︑その表題を示すと次のとおりである︒ 森秀雄 ︵北海道大学 ・当時︶によって発表されている ︒そこでは ︑五

(注)本報告書に掲載している数値は端数を四捨五入しているため、表中の数値の合計が表に示されている合計

“〇~□までの数字を表示する”というプログラムを組み、micro:bit

   遠くに住んでいる、家に入られることに抵抗感があるなどの 療養中の子どもへの直接支援の難しさを、 IT という手段を使えば

(注)本報告書に掲載している数値は端数を四捨五入しているため、表中の数値の合計が表に示されている合計

使用済自動車に搭載されているエアコンディショナーに冷媒としてフロン類が含まれている かどうかを確認する次の体制を記入してください。 (1又は2に○印をつけてください。 )

その太陽黒点の数が 2008 年〜 2009 年にかけて観察されな

都調査において、稲わら等のバイオ燃焼については、検出された元素数が少なか