2012年度 計算機システム演習 第6回 2012.06.01 福田 圭祐.

Slides:



Advertisements
Similar presentations
1 B10 CPU を作る 1 日目 解説 TA 高田正法
Advertisements

アルゴリズムと データ構造 第 3 回 基本的なデータ構造(2) : 配列 1. 前回の復習 アルゴリズムの計算量 最悪(最大)計算量 計算量の漸近的評価 (オーダ)  多項式時間アルゴリズム( polynomial time algorithm )  指数時間アルゴリズム( exponential.
2006/10/26 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第4回 配列(2) 情報・知能工学系 山本一公
2012年度 計算機システム演習 第3回 白幡 晃一.
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
計算技術研究会 C言語講座 第3回 Loops (for文 while文).
データ構造とアルゴリズム 第10回 mallocとfree
情報システム基盤学基礎1 コンピュータアーキテクチャ編 第2回 命令
坂井 修一 東京大学 大学院 情報理工学系研究科 電子情報学専攻 東京大学 工学部 電気工学科
実行時のメモリ構造(1) Jasminの基礎とフレーム内動作
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
基礎プログラミングおよび演習 第9回
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
プログラミング基礎I(再) 山元進.
2012年度 計算機システム演習 第4回 白幡 晃一.
App. A アセンブラ、リンカ、 SPIMシミュレータ
2006年度 計算機システム演習 第4回 2005年5月19日.
ソフトウェアとのインターフェース.
計算機システムⅡ 命令セットアーキテクチャ
第8回 プログラミングⅡ 第8回
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第3回 CPUの管理と例外処理 OSによるハードウェアの管理 CPUの構成、動作 CPUの管理 例外処理、割り込み処理 コンテキストスイッチ
第5回 CPUの役割と仕組み3 割り込み、パイプライン、並列処理
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
第3回目 2006/05/01.
第10回 プログラミングⅡ 第10回
型付きアセンブリ言語を用いた安全なカーネル拡張
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
坂井 修一 東京大学 大学院 情報理工学系研究科 電子情報学専攻 東京大学 工学部 電気工学科
勉強会その3    2016/5/1 10 8分35秒 データの表現 演算.
Cプログラミング演習 第7回 メモリ内でのデータの配置.
アルゴリズムとデータ構造1 2006年6月16日
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
第11回 プログラミングⅡ 第11回
コンパイラ資料 実行時環境.
オブジェクト指向プログラミングと開発環境
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
情報とコンピュータ 静岡大学工学部 安藤和敏
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
第5回 メモリ管理(2) オーバレイ方式 論理アドレスとプログラムの再配置 静的再配置と動的再配置 仮想記憶とメモリ階層 セグメンテーション
コンピュータアーキテクチャ 第 4 回.
計算機アーキテクチャ1 (計算機構成論(再)) 第二回 命令の種類と形式
コンピュータアーキテクチャ 第 4 回.
ネットワーク・プログラミング デバイスドライバと環境変数.
第4回 CPUの役割と仕組み2 命令の解析と実行、クロック、レジスタ
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
X64 函数呼び出し規約 長谷川啓
プログラミング 4 文字列.
コンパイラ 第12回 実行時環境 ― 変数と関数 ― 38号館4階N-411 内線5459
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
情報システム基盤学基礎1 コンピュータアーキテクチャ編
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
Presentation transcript:

2012年度 計算機システム演習 第6回 2012.06.01 福田 圭祐

本日の内容 (Outline) 動的メモリ割り当て: ヒープ領域にデータを確保 例外処理 動的配列: 動的に配列の領域を確保 動的メモリ割り当て: ヒープ領域にデータを確保 動的配列: 動的に配列の領域を確保 c.f. ) 前回は$spを用いてスタック領域上にデータを格納 例外処理 トラップ例外 サービス 番号($v0) 引数 返り値 意味 print_int 1 $a0(整数) 整数値を表示 print_string 4 $a0(文字列のアドレス) 文字列を表示 read_int 5 $v0(整数) 整数値を読込む read_string 8 $a0(バッファ) $a1(長さ) 文字列を読込む sbrk 9 $a0(メモリサイズ) $v0(アドレス) メモリを割り当て exit 10 プログラム終了

動的配列 sbrk システムコールで実行時(動的)に確保される配列 int* b = (int *)malloc(4*4) 静的配列: データセグメントで実行前から(静的に)サイズが定 義された配列 sbrk ($v0=9): メモリ領域割り当てを要求 引数 ($a0): 確保するメモリ量(Byte) 返り値 ($v0): 確保されたメモリの先頭アドレス li $v0, 9 li $a0, 16 # 4*4byte syscall # sbrk move $t0, $v0 int* b = (int *)malloc(4*4) int[4]の割り当て

動的配列のアドレス sbrk した結果... bの先頭アドレス:0x10020000 $v0 = 0x10020000 : メモリ 0x10020000 b[0] 0x10020004 b[1] 0x10020008 16バイト b[2] 0x1002000c b[3] 0x10020010

動的配列の操作 メモリアクセスはsw,lw メモリアクセス命令 データセグメント、スタック領域(スタックセグメント)、ヒープ領域 sw $x, n($y) $x の値をメモリのアドレス n + $y に代入 lw $x, n($y) メモリのアドレス n + $y にある値を $x に代入 アドレス メモリ 値 0x10020000 b[0] $y=0x10020000 n=4 0x10020004 sw b[1] $x lw

インデクスi にアクセスする場合、4倍(i*4)すればよい 動的配列の操作の例 b[i] 先頭のアドレス:$t0 = b インデックス:$a0 = i b[1] 先頭のアドレス:$t0 = b インデクス:1 add $t1, $a0, $a0 add $t1, $t1, $t1 add $t2, $t0, $t1 lw $v0, 0($t2) $t1 = 4*$a0 # 4+b lw $v0, 4($t0) $t2 = $t0 + 4*$a0 インデクスi にアクセスする場合、4倍(i*4)すればよい

動的配列 (サンプル) データ数を入力させ、 そのサイズnの配列bを b[i]=iと初期化するプログラ ム while(i == 0) { m8.s .text main: li $v0, 5 syscall add $a0, $v0, $v0 add $a0, $a0, $a0 li $v0, 9 move $t0 ,$v0 move $t1, $v0 while: beq $t1, $zero, end addi $t1, $t1, -1 add $t2, $t1, $t1 add $t2, $t2, $t2 add $t2, $t0, $t2 sw $t1, 0($t2) j while end: jr $ra データ数を入力させ、 そのサイズnの配列bを b[i]=iと初期化するプログラ ム $v0*4 Byte $t1: 配列のサイズ while(i == 0) { i--; b[i] = i } $t0 + $t1*4 Byte

動的配列 (サンプル) データ数を入力させ、 そのサイズnの配列bを b[i]=iと初期化するプログラ ム while(i == 0) { m8.s .text main: li $v0, 5 syscall move $t1, $v0 add $a0, $v0, $v0 add $a0, $a0, $a0 li $v0, 9 move $t0 ,$v0 while: beq $t1, $zero, end addi $t1, $t1, -1 add $t2, $t1, $t1 add $t2, $t2, $t2 add $t2, $t0, $t2 sw $t1, 0($t2) j while end: jr $ra データ数を入力させ、 そのサイズnの配列bを b[i]=iと初期化するプログラ ム $t1: 配列のサイズ $v0*4 Byte while(i == 0) { i--; b[i] = i } $t0 + $t1*4 Byte

例外処理 Java の例外処理 CPU の例外処理 自分で書いた catch 文の中 の処理が行われる OSカーネル内で用意された処 理が行われる プログラム try { : } catch (Exception e) { 例外処理 } 例外発生 例外発生 例外処理 OSカーネル ※ OSカーネル OSの基本機能を実装したプログラム群 e.g,) 入出力、メモリ管理、プロセス間通信

例外の種類 プログラムの不正実行で発生するもの プログラムから明示的に発生させるもの 不正アドレスのアクセス 例: lw $t0, 0x00000001 Exception 4 [Address error in inst/data fetch] プログラムから明示的に発生させるもの OSカーネルでしか使えない 機能を利用するため ファイル入出力 メモリ割り当てなど プログラムから明示的に発生させる例外 例外番号 内容 8 syscall 例外 13 トラップ例外

kernel text segment のアドレスを指定(MIPS32) 例外処理の流れ プログラム 例外ハンドラ アドレス 0x80000180 から 実行される $k0, $k1 レジスタが使え る : li $v0, 5 syscall move $t0, $v0 例外発生 復帰 今回実装する    プログラム (myexceptions.s) 例外ハンドラ .kdata : .ktext 0x80000180 read_int の処理 OSカーネル kernel text segment のアドレスを指定(MIPS32)

例外ハンドラの実装の流れ レジスタ退避 例外番号の取得 (実行したい処理) PC(プログラムカウンタ)の調整 レジスタ復帰 $at 例外ハンドラ内で使用するレジスタ 例外番号の取得 (実行したい処理) PC(プログラムカウンタ)の調整 レジスタ復帰 例外ハンドラ内で使用したレジスタ 例外ハンドラ終了命令(eret)

1. レジスタの退避 例外ハンドラ内で使うレジスタを保存 callee-saveで行う (=> $sを使用) caller-saveだと例外が発生する命令ごとにレジスタを退避 例外処理がプログラムの実行に悪影響を与えないようにする .kdata save_s0: .word 0  # $s0を保存するメモリ領域 .ktext 0x80000180 .set noat  # $atを扱うことを許可する move $k1, $at  # 疑似命令が使うレジスタを$k1に保存 .set at  # $atを扱うことを不許可にする sw $s0, save_s0  # $s0を使うなら元の値を退避保存

擬似命令(再) MPIS には無い命令 命令自体はあるが、オペ ランドが違う命令 擬似命令内では$atレジスタが使用される ★ ★ blt $s1, $s2, label 命令自体はあるが、オペ ランドが違う命令 sw $t1, A($t0) slt $at, $s1, $s2 bne $at, $zero, label lui $at, 4097 #A addu $at, $at, $t0 sw $t1, 0($at) ★ 擬似命令内では$atレジスタが使用される 例外ハンドラ内で $at レジスタが上書きされると困る(  ) ★ ※lui: load upper immediate ※addu: add unsigned

コプロセッサ メインプロセッサとは別のプロセッサが例外を管理する コプロセッサのレジスタには mfc0, mtc0 命令でアクセス できる 例外番号、例外発生アドレス…など コプロセッサのレジスタには mfc0, mtc0 命令でアクセス できる mfc0 CPUレジスタ, コプロセッサレジスタ コプロセッサのレジスタの内容をCPUレジスタにコピー mtc0 CPUレジスタ, コプロセッサレジスタ CPUレジスタの内容をコプロセッサのレジスタにコピー

※srl: shift right logical 2. 例外番号の取得 コプロセッサの Cause レジスタに発生した例外番号が 入っている $13 レジスタ 例外コード mfc0 $k0, $13 srl $k0, $k0, 2 # 2ビット右シフト andi $k0, $k0, 0x1f # 下位5ビットを取り出す ※srl: shift right logical

3. 例外ハンドラで行う処理 例外に応じた処理をする 不正メモリアクセス syscall エラーを表示 プログラムを終了 $v0 で指定されたサービスを実行 $a0〜$a3を引数とする $v0 に結果を代入

4. PC の調整 例外処理終了後、次の命令から実行再開 mfc0 $k0, $14 addiu $k0, $k0, 4 (サブルーチン呼び出しの場合は jal 命令が $ra レジスタに次の命令 のアドレスを入れてくれた) EPC(Exception Program Counter)レジスタに例外が発生した 命令のアドレスが入っている コプロセッサの $14 レジスタ EPC の値を 4 増やせば次の命令から再開できる mfc0 $k0, $14 addiu $k0, $k0, 4 mtc0 $k0, $14

5. レジスタの復帰と6. 例外ハンドラ終了 例外発生時と全てのレジスタの内容を同じにしておく必 要がある syscall の場合は $v0 だけ変わる eret 命令で EPC レジスタが指すアドレスから実行を再開 lw $s0, save_s0 # $s0を復帰 .set noat # $atを扱うことを許可 move $at, $k1 # $atを復帰 .set at eret

スタートアップルーチン myexceptions.s には main ルーチンを呼び出す初期ルー チンも書かなければならない .text .globl __start # 他のモジュールから 呼び出せるようにする __start: jal main # mainを呼び出す li $v0, 10 syscall # exitシステムコール 注:globalではない

まとめ:例外ハンドラ .kdata #1. 退避用の配列の宣言 .ktext 0x80000180 # 1. 例外ハンドラで使用するレジスタを退避($atと$s0など) # 2. Causeレジスタから例外番号を取得 # 3. 実行したい処理 # 4. EPCレジスタを4進める # 5. 退避したレジスタを復帰 eret : .text .globl __start    __start: # mainルーチンを呼び出す初期ルーチン

SPIM での例外ハンドラ デフォルトで <install directory>/lib/exceptions.s が使わ れている 変更するには -exception_file オプションをつけて xspim を起 動すればよい xspim –exception_file [path] Loaded: myexceptions.s と表示される $ xspim –exception_file ./Kadai/ex06/myexceptions.s

補足:全32本のレジスタ 使用できるレジスタ 使用できないレジスタ 1 $at (assembler temporary) reserved by the assembler 26-27 $k0-$k1 reserved for use by the interrupt/trap handler

課題

課題1 データ数、データを入力させ、全てのデータの和を計算し、 出力するプログラムを書け 次の2つのサブルーチンを実装すること 実行例 create_array 引数:配列の要素数($a0) 戻り値:配列の先頭アドレス($v0) 要素数分の動的配列を作成し、受け取ったデータ で初期化する 内部で read_int syscallを データ数 回呼び出してよい calc_sum 引数:配列の先頭アドレス($a0)、配列のサイズ($a1) 戻り値:和($v0) caller-save、あるいはcallee-saveで適切にレジスタを退避・ 復元すること 実行例 count=5 1 3 2 4 5 sum=15

課題1:ヒント # 必要に応じてレジスタを退避させる # 必要に応じてプロンプト(count=など) # を表示させること .text main: # 要素数を読込む li $v0, 5 syscall move $t0, $v0 # create_arrayを呼び出す move $a0, $t0 jal create_array # calc_sumを呼び出す move $a0, $v0 move $a1, $t0 jal calc_sum # ナビゲーション(sum=など)を表示 # 結果を表示 create_array # $a0: 作成する配列のサイズ # $v0: 配列の先頭アドレス # read_int syscallを $a0 回呼び出す # li $v0, 5 # syscall # move $t0, $v0 calc_sum # $a0: 配列の先頭アドレス # $a1: 配列のサイズ # $v0: 和の結果

課題2 myexceptions.s を作成し、引数の値を10倍するシステムコールを作 れ 引数: $a0 (10したい値)、サービス番号:$v0=100 返り値:$v0 ($a0 * 10) ここではトラップ例外をわざと発生させる teq $zero, $zero でトラップ例外を発生させられる ※ teq: Trap if Equal li $v0, 100 # システムコール番号100 li $a0, 55 # 10倍したい値 teq $zero, $zero # トラップ例外を発生させる move $a0, $v0 li $v0, 1 syscall # 10倍した値を表示 新しいシステムコールを使うプログラム例

課題2:補足 myexceptions.s .kdata #1. 退避用の配列の宣言 .ktext 0x80000180 #1. 退避用の配列の宣言 .ktext 0x80000180 # 1. 例外ハンドラで使用するレジスタを退避($atと$t0など) # 2. Causeレジスタから例外番号を取得 # 3. 例外番号が13以外ならdoneにジャンプ # 3. システムコール番号($v0)が100以外ならdoneにジャンプ # 3. 引数($a0)の値を10倍(mul命令)して$v0に代入 done: # 4. EPCレジスタを4進める # 5. 退避したレジスタを復帰 eret : .text .globl __start    __start: # mainルーチンを呼び出す初期ルーチン

課題提出 〆切: 6/15 (金) 23:59 提出物:以下のファイルを圧縮したもの 提出方法: Webから提出 〆切: 6/15 (金) 23:59 提出物:以下のファイルを圧縮したもの ドキュメント(pdf,plain txt,wordなんでも可) 課題1,2の実行結果 感想、質問等 プログラムソース 課題1,2 提出方法: Webから提出 授業のページからリンク パスワードを忘れてしまった人は佐藤まで