b10 cpu 1
Download
Skip this Video
Download Presentation
B10 CPU を作る 1 日目 解説

Loading in 2 Seconds...

play fullscreen
1 / 31

B10 CPU 1 - PowerPoint PPT Presentation


  • 190 Views
  • Uploaded on

B10 CPU を作る 1 日目 解説. TA 高田正法 [email protected] はじめに. 下のページに目を通すようにしてください。 http://www.mtl.t.u-tokyo.ac.jp/~mtakada/jikken_b10/ このスライドも上記の場所にあります。. 今日説明する内容. 実験の目的、内容 この実験で扱う道具について SPIM MIPS アーキテクチャ 課題 1 ~ 3 を行うために必要な知識 レジスタ 命令 システムコール MIPS 用プログラム記述の例. 実験の目的.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'B10 CPU 1' - andrew


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2
はじめに
  • 下のページに目を通すようにしてください。
    • http://www.mtl.t.u-tokyo.ac.jp/~mtakada/jikken_b10/
    • このスライドも上記の場所にあります。
slide3
今日説明する内容
  • 実験の目的、内容
  • この実験で扱う道具について
    • SPIM
    • MIPSアーキテクチャ
  • 課題1~3を行うために必要な知識
    • レジスタ
    • 命令
    • システムコール
  • MIPS用プログラム記述の例
slide4
実験の目的
  • RISC型プロセッサの構造、動作を理解する
    • 命令セットを理解する
    • 命令をMIPSシミュレータ”SPIM”に追加することによって、プロセッサの動作に関する理解を深める
slide5
実験の内容
  • MIPSの命令セットを理解する
    • アセンブラでプログラムを書く
      • 課題1~3
  • プロセッサの動作を理解する
    • 構成図を見て考える
      • 課題4~5,8
    • シミュレータを用いて、命令追加を行う
      • 課題6~7
    • シミュレータと実機の違いについて考える
      • 課題8
slide6
SPIMとは?
  • RISCプロセッサ MIPS R2000のシミュレータ
  • 以下の機能をサポート
    • アセンブリ言語からの直接読み込み
    • プロセッサの状態表示
    • ステップ実行
    • 簡単な入出力
slide7
MIPSとは?
  • RISC型プロセッサの一種
    • 機能が単純な命令のみを持ち、複雑な機能は命令の組み合わせでサポートする
    • メモリを扱う命令が、他の命令と分離されているのが特徴
  • 32個の32bitレジスタを持つ
    • レジスタ:計算をするための作業領域
slide8
メモリとレジスタの違い
  • メモリ
    • ○ 大きい(2^32Byteなど)
    • ○ アクセスする領域(アドレス)も変数
    • × 演算命令で直接扱えない
    • × 遅い
  • レジスタ
    • ○ 演算命令で直接扱える
    • ○ 速い
    • × 小さい(32bitレジスタが32個)
    • × アクセスする領域(レジスタ番号)は命令内で明示
slide9
レジスタの種類(1) – 汎用レジスタ
  • $t0~$t9
    • ユーザー用のレジスタ
    • サブルーチン(関数)を呼び出す際には、呼び出す側で値を保存しておく必要がある
  • $s0~$s7
    • ユーザー用のレジスタ
    • 呼び出されたサブルーチン側で、中身を保存する必要がある
slide10
レジスタの種類(2) – 関数呼び出し用
  • $a0~$a3
    • サブルーチン(関数)を呼び出す際に、引数をこれに入れる
  • $v0~$v1
    • サブルーチン(関数)からの戻り値をここに入れる
  • $ra
    • サブルーチン(関数)を呼び出した側の、プログラム番地を保存する
slide11
レジスタの種類(3) – 特殊なレジスタ
  • $zero
    • 常に0が入っているレジスタ
  • $sp
    • スタックの先頭のアドレスが格納されるレジスタ
slide12
レジスタの種類(4) – 使わないもの
  • 使ってはいけないレジスタ
    • $at
      • 疑似命令を展開する時に使われるレジスタ
      • ここでいう疑似命令: ソースファイルに書くことが可能であるが、実際には複数の実在する命令に展開される命令のこと(例:blt)
    • $k0~$k1
      • OS予約レジスタ
  • 気にしなくて良いレジスタ
    • $gp, $fp
slide13
プロセッサの命令の種類
  • メモリ←→レジスタのデータのやり取りをする命令
    • いわゆるload/store
  • レジスタを用いて計算をする命令
    • 算術演算、論理演算その他
  • 次に実行する命令を変える命令
    • 条件分岐命令
      • C言語のif, for, whileなどで使われる
    • 無条件ジャンプ命令
      • C言語での関数呼び出しなどで使われる
load store
load/storeの例

1Word(32bit)

1Word(32bit)

1Byte

1Byte

1Byte

1Byte

1Byte

1Byte

1Byte

1Byte

x x+1 x+2 x+3 x+4…(番地)

  • lw $t0, 4($t1)
    • メモリの($t1 + 4)番地に書かれている値(32bit)を、$t0レジスタに格納する
    • $t0 = *($t1 + 1);
      • +1 なのは、+4番地=32bit向こう=1要素進んだところだから
  • sw $s2, 0($t0)
    • $s2の中身(32bit)を、メモリの($t0+0)番地に格納する
    • *($t0) = $s2;
slide15
演算命令の例
  • addi $t0, $t1, 1
    • $t0 = $t1 + 1;
  • or $s0, $s1, $s2
    • $s0 = $s1 | $s2;
slide16
制御命令の例
  • bne $t0, $t1, LABEL
    • $t0 != $t1 ならば、次からは、LABEL番地から始まる命令列を実行する
    • if( $t0 != $t1 ) goto LABEL;
  • jal LABEL
    • $raに、jal命令の番地+4を格納し、次からはLABEL番地から始まる命令列を実行する
    • サブルーチン(関数)呼び出しに使われる
syscall
syscallの使い方
  • SPIMでは、キーボードからの入力/画面への出力を、syscallを使って行います
  • $v0にシステムコール番号を入れることによって、数種類の機能を実現できます
  • 詳しくは、SPIMマニュアルの8ページを参照してください
slide18
システムコールの例
  • $t0(整数型)の中身を画面に表示
    • li $v0, 1 # $v0 = 1;
    • move $a0, $t0 # $a0 = $t0;
    • syscall
  • メモリの$t0番地から始まる文字列を表示
    • li $v0, 4 # $v0 = 4;
    • move $a0, $t0 # $a0 = $t0;
    • syscall
  • プログラムの実行を終了
    • li $v0, 10
    • syscall
slide20
具体例
  • このような関数を考えましょう
    • numという配列が渡されたときに、先頭n要素の和を返す関数

int sum(int n, int num[]){

int sum = 0;

int i;

for( i = 0; i < n; i++ ){

sum += num[i];

}

return sum;

}

slide21
C言語からアセンブリ言語へ
  • C言語の変数は、主に2種類
    • static変数
      • プログラムのどこからでも見ることのできる変数
      • コンパイル時に、静的にメモリに割り当てられる
    • local変数
      • 同じ関数内でのみ参照可能
      • 実際には以下のいずれかに割り当てます
        • レジスタ ←ほとんどこちらだけで事足ります
        • メモリのスタック領域(※坂井先生の資料8ページ参照)
slide22
ソースファイルの書式

.data #お約束

ここに、static変数に対応する部分を

”.word”等の疑似命令を使って書く

.text #お約束

.globl main #お約束

main: #お約束

ここからプログラムを書く

# “#”から行末まではコメントになります

slide23
for文の展開
  • for( i = 0; i < n; i++)をアセンブリ言語で書きましょう
  • nは、$a0に入っていると仮定
  • iは$t0に割り当てましょう

li $t0, 0 # i = 0;

loop_start:

何か処理…

addi $t0, $t0, 1 # i++

bne $t0, $a0, loop_start # if( i != n ) goto loop_start;

slide24
メモリからの読み出し
  • $a1に、先頭の要素のアドレスが入っていると仮定しましょう
  • $t1に、現在の要素のアドレスを入れましょう
  • $t2に、各要素の値を一時的に格納しましょう
  • $v0に、合計の値を格納しましょう

li $t0, 0 # i =0;

li $v0, 0 # sum = 0;

move $t1, $a1 # $t1 = $a1;

loop_start:

lw $t2, 0($t1) # $t2 = *($t1);

add $v0, $v0, $t2 # $v0 = $v0 + $t2;

addi $t1, $t1, 4 # 次の要素は4番地(32bit)先

addi $t0, $t0, 1 # i++;

bne $t0, $a0, loop_start # if( I != n ) goto loop_start;

slide25
関数ができました

sum:

li $t0, 0 # i =0;

li $v0, 0 # sum = 0;

move $t1, $a1 # $t1 = $a1;

loop_start:

lw $t2, 0($t1) # $t2 = *($t1);

add $v0, $v0, $t2 # $v0 = $v0 + $t2;

addi $t1, $t1, 4 # 次の要素は4番地(32bit)先

addi $t0, $t0, 1 # i++;

bne $t0, $a0, loop_start # if( i != n ) goto loop_start;

jr $ra # 関数呼び出し元へ

slide26
この関数の仕様
  • 配列に入っている各要素の和を計算する
    • $a0: 要素数
    • $a1: 先頭のアドレス
    • $v0: 計算結果
slide27
呼び出し元を書きましょう
  • こんなプログラムだとしましょう

int numOfElements=4; // static変数

int elements[] = {1, 2, 3, 4}; // static変数

void main(){

int s = sum( numOfElements, elements);

printf( “%d”, s);

}

slide28
呼び出し元

main:

lw $a0, numOfElements # $a0 = numOfElements;

la $a1, elements # $a1 = &(elements[0]);

jal sum # $v0 = sum($a0, $a1);

move $a0, $v0 # $a0 = s;

li $v0, 1 #

syscall # prinf(“%d”, s);

li $v0, 10

syscall # exit();

static
static変数部分
  • 今回は、numOfElementsとelementsがstatic変数

.data

numOfElements: .word 4 # int numOfElements=4;

elements: .word 1, 2, 3, 4 # int elements[]={1, 2, 3, 4};

これで、numOfElementsが”4”の入ったアドレス、elementsが1, 2, 3, 4が入ったメモリの先頭のアドレスを指すようになります

slide30
完了
  • http://www.mtl.t.u-tokyo.ac.jp/~mtakada/jikken_b10/にあるsum.sがこのプログラムの完成品です
  • SPIMで読み込んで、実行してみましょう
    • .word部分の値を変えて、結果が変わることを確認してみましょう
slide31
駆け足になりましたが
  • 各内容についての詳細は以下を参照してください
    • レジスタの一覧
      • SPIMマニュアル 10ページ
    • 命令の一覧
      • SPIMマニュアル 13ページ~
    • システムコールの一覧
      • SPIMマニュアル 8ページ~
    • .data部分に書くことのできるもの
      • SPIMマニュアル 7ページ~
ad