スライド 1

Similar documents
スライド 1

スライド 1

ex04_2012.ppt

ex05_2012.pptx

スライド 1

スライド 1

スライド 1

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

ソフトウェア基礎技術研修

Microsoft PowerPoint ppt

ソフトウェア基礎技術研修

Microsoft PowerPoint - 11.pptx

スライド 1

第2回

Microsoft PowerPoint - C言語の復習(配布用).ppt [互換モード]

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft PowerPoint ppt

Microsoft PowerPoint ppt

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

命令セットの構成例 a) 算術 演算命令 例 )ADD dest, source : dest dest + source SUB dest, source : dest dest - source AND dest, source : dest dest AND source SHR reg, c

計算機アーキテクチャ

gengo1-11

Microsoft PowerPoint - prog04.ppt

02: 変数と標準入出力

Microsoft PowerPoint - NxLec ppt

< F2D837C E95CF CF68A4A94C5816A2E6A>

プログラミング実習I

Prog1_10th

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint - Chap2 [Compatibility Mode]

プログラミング実習I

COMET II のプログラミング ここでは機械語レベルプログラミングを学びます 1

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

02: 変数と標準入出力

PowerPoint プレゼンテーション

第1回 プログラミング演習3 センサーアプリケーション

SuperH RISC engine C/C++ コンパイラ Ver.7 不具合内容 - 過去のお知らせ SuperH RISC engine C/C++ コンパイラ Ver.7 台における不具合内容を以下に示します のチェックツールをルネサスエレクトロニクス株式会社のホームページ

Microsoft PowerPoint - Sol7 [Compatibility Mode]

計算機アーキテクチャ

Microsoft Word - 3new.doc

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

スライド 1

関数の動作 / printhw(); 7 printf(" n"); printhw(); printf("############ n"); 4 printhw(); 5 関数の作り方 ( 関数名 ) 戻り値 ( 後述 ) void である. 関数名 (

コンピュータ工学Ⅰ

スライド 1

Microsoft PowerPoint - ProcML-12-3.ppt

Microsoft Word - no202.docx

Microsoft PowerPoint - Chap5 [Compatibility Mode]

Microsoft PowerPoint pptx

Microsoft PowerPoint - prog03.ppt

Cコンパイラパッケージお知らせ

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

PowerPoint プレゼンテーション

模擬試験問題(第1章~第3章)

ex03_2012.ppt

slide5.pptx

Microsoft PowerPoint ppt

PowerPoint Presentation

ソフトウェア基礎技術研修

PowerPoint Presentation

Microsoft Word - Training10_プリプロセッサ.docx

1 はじめに このアプリケーションは 計算機ハードウェア論 のアセンブリ言語 ( 超簡単命令セット ) の理解を助けるために製作されました 便宜的に機能を追加 削除した箇所があるため このアプリケーション上での動き方が実際のCPUでの動き方と異なる場合があることに留意してください このアプリケーショ

6. パイプライン制御

Microsoft PowerPoint - NxLecture ppt [互換モード]

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

Microsoft PowerPoint - 09.pptx

SuperH RISC engineファミリ用 C/C++コンパイラパッケージ V.7~V.9 ご使用上のお願い

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

Microsoft Word - 中間試験 その1_解答例.doc

Microsoft PowerPoint - C_Programming(3).pptx

Microsoft Word - no103.docx

スライド 1

情報処理演習 B8クラス

コンピュータ工学Ⅰ

Microsoft PowerPoint - Chap4 [Compatibility Mode]

CASL入門

Microsoft PowerPoint - kougi7.ppt

Microsoft PowerPoint - lec10.ppt

02: 変数と標準入出力

RH850の割り込み/例外実現方法 CC-RHアプリケーションガイド

memo

プログラミングI第10回

PowerPoint プレゼンテーション

第2回講義:まとめ

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

また RLF 命令は 図 2 示す様に RRF 命令とは逆に 各ビットを一つずつ 左方向に回転 ( ローテイト ) する命令である 8 ビット変数のアドレスを A とし C フラグに 0 を代入してから RLF A,1 を実行すると 変数の内容が 左に 1 ビットシフトし 最下位ビット (LSB)

Microsoft Word - Cプログラミング演習(10)

02: 変数と標準入出力

文字列 2 前回の授業ではコンピュータ内部での文字の取り扱い 文字型の変数 文字型変数への代入方法などを学習した 今回は 前回に引き続き 文字処理を学習する 内容は 標準入出力 ( キーボード ディスプレイ ) での文字処理 文字のファイル処理 文字を取り扱うライブラリ関数である 標準入出力 Lin

数値計算

第2回

PowerPoint プレゼンテーション

4 分岐処理と繰返し処理 ( 教科書 P.32) プログラムの基本的処理は三つある. (1) 順次処理 : 上から下に順番に処理する ぶんきそろ (2) 分岐処理 : 条件が揃えば, 処理する はんぷく (3) 反復処理 : 条件が揃うまで処理を繰り返す 全てのプログラムは (1) から (3) の

memo

講習No.12

Microsoft PowerPoint L07-Imperative Programming Languages-4-students ( )

プログラミング基礎

CプログラミングI

主記憶の使われ方 システム領域 SP スタックポインタ システム用 スタック用 プログラム起動時に OS によって確 保される (SP が決められる ) プログラム用 メインルーチン プログラム領域 命令コードの列定数 変数用領域サブルーチン命令コードの列 先頭番地は リンク時に OS によって決め

PowerPoint プレゼンテーション

Transcription:

東北大学工学部機械知能 航空工学科 2019 年度クラス C D 情報科学基礎 I 7. MIPS の命令と動作 分岐 ジャンプ 関数呼出し ( 教科書 7 章命令一覧は p.113) 大学院情報科学研究科 鏡慎吾 http://www.ic.is.tohoku.ac.jp/~swk/lecture/

分岐 ジャンプ命令 条件文や繰り返し文などを実現するには, 命令の実行順の制御が必要 (C 言語 ) if (x == y) { x = x + 1;... ただし, 変数 x, y の内容がそれぞれレジスタ s0, s1 に置かれているとする (MIPS アセンブリ言語 ) bne $s0, $s1, L1 # $s0 $s1 ならば L1 へ分岐 addu $s0, $s0, 1 L1:... ラベル 2

資料 : 主な分岐命令, 比較命令 命令 beq $a, $b, L bne $a, $b, L 説明 $a = $b ならばラベル L へ分岐 (branch on equal) $a $b (branch on not equal) slt $c, $a, $b 符号つきで $a < $b ならば $c 1; さもなくば $c 0 sltu $c, $a, $b 符号無しで $a < $b ならば $c 1; さもなくば $c 0 sgt $c, $a, $b sgtu $c, $a, $b sle $c, $a, $b sleu $c, $a, $b sge $c, $a, $b sgeu $c, $a, $b 符号つきで $a > $b (set on greater than) 符号無しで $a > $b (set on greater than unsigned) 符号つきで $a $b (set on less than or equal) 符号無しで $a $b (set on less than or equal unsigned) 符号つきで $a $b (set on greater than or equal) 符号無しで $a $b (set on greater than or equal unsigned) slt, sltu 以外の比較命令はマクロ命令 3

(C 言語 ) if (x < y) { x = x + 1; else { x = x + 2;... 例 : if else 文 ただし, 変数 x, y の内容がそれぞれレジスタ s0, s1 に置かれているとする (MIPS アセンブリ言語 ) slt $t0, $s0, $s1 beq $t0, $zero, L1 # $s0 < $s1 でないならL1へ分岐 addu $s0, $s0, 1 j L2 # 無条件に L2 へジャンプ L1: addu $s0, $s0, 2 L2:... 4

(C 言語 ) while (x < y) { x = x + 1; 例 : while 文 ただし, 変数 x, y の内容がそれぞれレジスタ s0, s1 に置かれているとする (MIPS アセンブリ言語 ) L1: slt $t0, $s0, $s1 # x < y なら $t0 1; さもなくば $t0 0 beq $t0, $zero, L2 # 比較結果が偽 ( ゼロ ) なら L2 へ addu $s0, $s0, 1 # x x + 1 j L1 L2:... 5

関数呼出し (C 言語 ) int func(int a, int b) { a = a + b; return a; int main() { int x, y, z; 関数呼出しは単に j 命令でジャンプするだけでは実現できない ( 元の位置に戻って来る必要がある ) x = func(5, 1); y = func(8, 2); z = func(x, y);... ただし, 関数 main 内の変数 x, y, z の内容がそれぞれレジスタ s0, s1, s2 に置かれているとする 6

(MIPS アセンブリ言語 ) 関数呼出しの実行例 func: addu $a0, $a0, $a1 move $v0, $a0 # 戻り値には $v0, $v1 を使う jr $ra # $ra のアドレスへジャンプ main: # 初期化省略 li $a0, 5 # 引数には $a0~$a3 を使う li $a1, 1 jal func # func へジャンプし, 戻り先アドレスを $ra へ move $s0, $v0 li $a0, 8 li $a1, 2 jal func move $s1, $v0 move $a0, $s0 move $a1, $s1 jal func move $s2, $v0 7

資料 : 主なジャンプ命令 命令 説明 j L ラベル L へジャンプ (jump) jal L jr $r ラベル L へジャンプすると同時に, 次の命令アドレスを $ra ($31) に保存 (jump and link) レジスタ r に保存されたアドレスへジャンプ (jump register) 8

分岐 ジャンプ命令の動作 PC 次 PC 計算 (2) 分岐判定 (3) 分岐先アドレス計算 mux 命令デコーダ (1) レジスタ読み出し 32x32ビットレジスタ メモリ mux 制御回路 32 ビット ALU アドレス (32 ビット ) データ (8, 16, 32 ビット ) 9

参考 : 次 PC 計算 の処理 分岐条件が成立していないなら, PC + 4 成立しているなら, 条件分岐命令のとき : PC + 4 定数フィールド値 ジャンプ命令のとき : PC の下位 28 ビットを 4 定数フィールド値で置換 命令長は常に 4 バイトなので, 分岐 ジャンプ先のアドレスは必ず 4 の倍数になる この講義では 遅延分岐 は無視する 10

MIPS の命令フォーマット MIPS の命令は基本的に以下の 3 フォーマットに分類される R 形式 31 26 25 21 20 16 15 11 10 6 5 0 OP rs rt rd シフト量 func レジスタ間演算, シフト命令 ( 即値版も含む ) など I 形式 31 26 25 21 20 16 15 0 OP rs rt 定数 ( 即値 / アドレスオフセット ) レジスタ - 即値間演算, ロード ストア, 分岐命令など 31 26 25 0 J 形式 OP 定数 ( ジャンプ先 ) ジャンプ命令など 11

実際の関数呼出し 前の関数呼出しの例は, 簡単に済むように巧妙に作られた例である. 実際には以下のようなことを考えなくてはならない. 呼出された関数はどのレジスタを使えばよいのか? 特に, 呼出された関数が呼出し元のレジスタを破壊しないためにはどうすればよいのか? ra は一つしかないが, 関数を多重で呼出す場合は? 4 つを超える引数の受け渡しは? これらはスタックと呼ばれるデータ構造をメモリ内に構築することで取り扱われる 12

関数呼出時のプログラムの流れ int g() { int f() { g(); int main() { f(); main f の呼出時に $ra がセットされる $s0 を使っており,f の呼出後も使い続けるとする f 呼出 g の呼出時に $ra は上書きされてしまう こちらでも $s0 を使うとどうなる? g 呼出 リターン リターン 13

int f() { g(); スタックメモリ addu $sp, $sp, -20 addu $sp, $sp, 20 push pop $sp 0x8020 $sp 0x800c $sp 0x8020 0x8020 f() のスタックフレーム 0x8020 f() のスタックフレーム 0x8020 f() のスタックフレーム 0x8010 0x8010 0x800c g() のスタックフレーム 0x8010 0x8000 0x8000 0x8000 14

MIPS の場合のレジスタ スタック利用ルール 関数呼出時のレジスタ利用規約 t0~t9 は, 壊されたくないなら呼出し側がスタックに退避 ( すなわち, 主にテンポラリ用と想定されている ) s0~s8 は, 呼出された側が使いたいならスタックに退避してリターン時に原状回復する 関数を多重で呼出す場合は ra もスタックに退避 4 つを超える引数はスタックに積んでから関数を呼出す 15

典型的なメモリマップ 高位アドレス int global_var; void func() { int a, b; static int static_var;... int main() { int x, y; スタックポインタ ($sp) グローバルポインタ ($gp) int *p = (int *) malloc(256); スタック ( 局所変数 ) 動的確保領域 大域変数 静的変数等 プログラム 低位アドレス 16

例 : ポケットモンスター 5 かい バグ ゲームボーイ用ゲーム ポケットモンスター赤 ポケットモンスター緑 ( 任天堂, 1996) には, プレイヤが保有している道具やポケモン ( ゲーム世界内の架空生物 ) などを並べ替える機能があったが, この機能の実装に不具合があり, 特定の操作によって本来は存在しないはずの道具 ( 俗に バグアイテム ) を入手することができた. 道具を使ったときに生じる効果は, 道具ごとに定められているアドレスに対する呼出しによって実現されており, バグアイテムを使用すると想定外のアドレスへの呼出しが生じた. 特に 5 かい という名称で表示されるバグアイテムの場合は, 呼出されるアドレス以降がポケモンの種類やその状態等を保持するメモリ領域となっており, プレイヤがある程度自由に設定することができた. 結果として, 任意のプログラムを作成し実行することが可能となっていた. 17

https://www.youtube.com/watch?v=ij7mrjiseo0 18

https://www.youtube.com/watch?v=baxxp6b7anq 19

例 : バッファ オーバラン攻撃 int getnum() { char buf[8]; gets(buf); /* 入力文字列を配列 buf に保存 */ return atoi(buf); /* 文字列 整数 */ このような問題があるので,gets, scanf のように配列長を指定せずに入力を読み込む関数は, 使用が推奨されない getnum() のスタックフレーム 高位アドレス return address buf sp 低位アドレス 20

実際のコンパイラが出力するコードを見てみる https://godbolt.org/ 左側の言語として C を選択 適当な C の関数を入力右側のコンパイラとして ( 例えば ) MIPS gcc 5.4 を選択 その右の入力欄 ( コンパイラへのオプション指定 ) に : -O -fomit-frame-pointer -fno-delayed-branch -O0 とすると最適化がオフになる int test(int x, int y) { if (x == y) { x = x + 1; return x; $2 は $v0, $31 は $ra 鏡慎吾 ( 東北大学 ): 計算機工学 2017 (7) test: $L2: move $2,$4 bne $4,$5,$L2 nop nop は気にしない addiu $2,$4,1 j $31 nop $4, $5, $6, $7 は引数 21

練習問題 (1) 以下に示すプログラムは, ある値を 2 進数で表した際に, その中に含まれる 1 のビットの数を数えるものである. lw $s0, 0($s1) move $t0, $zero L1: and $t1, $s0, 1 addu $t0, $t0, $t1 srl $s0, $s0, 1 bne $s0, $zero, L1 sw $t0, 0($s1) レジスタ $s1 の内容が指すアドレスに値 13 が格納されている状態でこのプログラムを実行した. (1) 実行終了時の, レジスタ $s0,$t0,$t1 の内容を示せ. (2) ラベル L1 で指される命令は, 何回実行されるか答えよ. 22

L1: lw $s0, 0($s1) move $t0, $zero and $t1, $s0, 1 addu $t0, $t0, $t1 srl $s0, $s0, 1 bne $s0, $zero, L1 sw $t0, 0($s1) 解答例 $s0 = mem[$s1 + 0]; /* = 12 */ $t0 = 0; do { $t1 = $s0 & 1; $t0 = $t0 + $t1; $s0 = $s0 >> 1; while ($s0!= 0); mem[$s1 + 0] = $t0; (1) $s0 は計算対象で,1 ビットずつシフトして行き, 最後は 0 になる $t0 は最終結果で, ビット 1 の数になる. よって 3 $t1 は計算途中で使用し, ループごとに $s0 の最下位ビットを取り出すのに使われる. 最後は 1 になる (2) 4 回 23

練習問題 (2) 以下に示すプログラムは配列の中から最大値を探すものである. move $v0, $zero L1: lw $t0, 0($s0) ( 1) sltu $t1, $v0, $t0 beq $t1, $zero, L2 move $v0, $t0 ( 2) L2: addu $s0, $s0, 4 addu $s1, $s1, -1 bne $s1, $zero, L1 いま, 符号なし整数 (4 バイト ) が, メモリ上のアドレスが増える方向に 10, 20, 3, 22, 5 の順に並んでおり, この配列の先頭アドレスを $s0, 配列長 5 を $s1 に与えてこのプログラムを実行した. (1) プログラムの実行が終わった時点でのレジスタ $s1, $v0, $t0, $t1 の内容を示せ. (2) 1 及び 2 の命令がそれぞれ何回実行されるか答えよ. 24

解答例 move $v0, $zero L1: lw $t0, 0($s0) sltu $t1, $v0, $t0 beq $t1, $zero, L2 move $v0, $t0 L2: addu $s0, $s0, 4 addu $s1, $s1, -1 bne $s1, $zero, L1 $v0 = 0; do { $t0 = mem[$s0 + 0]; if ($v0 < $t0) { $v0 = $t0; $s0 = $s0 + 4; $s1 = $s1 1; while ($s1!= 0) (1) $s1 は処理すべき配列要素の残り数で, 終了時は 0 になる.$v0 はその時点までの最大値を保持するレジスタで, 終了時は全体の最大値 22 になる. $t0 は読み出した配列要素を格納するレジスタで, 終了時は最後の要素 5 になる.$t1 は, それまでの最大値が読み出した配列要素より小さければ 1 になるレジスタで ( これが 0 のときは L2 に分岐するため, 最大値の更新がスキップされる ), 最後のループでは 0 になる. (2) 1 は, 配列長が 5 なので 5 回実行される. 2 は, 最大値を更新するときのみ実行されるため 3 回実行される. 25

練習問題 (3) 以下に示すプログラムは配列の内容の総和をレジスタ $s2 に返すものである. move $s2, $zero L1: lw $t0, 0($s0) addu $s1, $s1, -1 addu $s2, $s2, $t0 addu $s0, $s0, 4 bne $s1, $zero, L1 いま, 整数 (4 バイト ) の配列の先頭アドレスをレジスタ $s0 に, 配列長 1000 をレジスタ $s1 に与え, このプログラムを実行した. (1) プログラムの実行が終わった時点でのレジスタ $s1 の内容を示せ. (2) ラベル L1 で指される lw 命令は, 何回実行されるか答えよ. (3) このプログラム全体で, いくつの命令が実行されるか答えよ.( 同じ命令が 2 回実行される場合,2 命令と数える ) 26

解答例 (1) $s1 は処理すべき配列要素の残り数で, 終了時は 0 になる. (2) 配列要素を読み出す命令で, 配列長分の 1000 回実行される. (3) 最初の move 命令は 1 回だけ, 他の 5 命令は 1000 回実行されるので, 合計 5001 命令が実行される. 27