0
@twrcd1227

MIPSアセンブリ言語入門1

概要

MIPSについてまとめてみた
MIPSのプログラムの実行はシミュレータのSPIMを使用している

Hello World

Hello Worldの表示

最初にHello Worldを表示するプログラムを作ってみる。

hello.asm
#Hello Worldを表示するプログラム

#データ
        .data
msg:    .asciiz "Hello World\n"

#テキスト

        .text
        .globl main
main:
  li    $v0, 4
        la        $a0, msg
        syscall
        jr        $ra

# end
実行結果
Hello World

hello.asmの説明

#の後はコメントアウト
プログラムはデータ領域とテキスト領域で構成される。

データ領域

データ領域とは変数値や計算の途中で一時的に使われる領域のこと。

hello.asmのデータ領域
        .data
msg:    .asciiz "Hello World\n"

1行目の.dataはデータ領域の開始の宣言を表す。
2行目のmsg: .asciiz "Hello World\n"はラベルmsgの宣言をしている。

ラベルを宣言することによって、このアドレスをmsgという記号で参照することができる。

テキスト領域

テキスト領域とはプログラムを配置する領域である。

hello.asmのテキスト領域
        .text
        .globl main
main:
  li    $v0, 4
        la        $a0, msg
        syscall
        jr        $ra

# end

1行目の.textでテキスト領域の開始の宣言をする。
2行目の.globl mainで下で定義されているmainというラベルがグローバル(このプログラムの外部から見える)であることを宣言する。
3行目でラベルmainを宣言。
4行目li $v0, 4は$v0レジスタに値4をロードする。
5行目la $a0, msg$a0はレジスタに付加パラメータ(この場合は表示する文字列を格納した領域のアドレス)をロードする。
6行目syscallはシステムコールを実行する。実行するシステムコールの種類は$v0で指す
7行目jr $raは呼び出しもとに戻る(return)。アドレスは$raに格納されている。

レジスタ

MIPSのレジスタは32個ある。

$s0〜$7 (16〜23)

プログラムの変数の値を保持

$t0〜$t7 (8〜15)

計算途中の一時的な値を保持

$zero (0)

常に0という値を持つ特別なレジスタ

アセンブリ命令

算術演算

add

add $s1, $s2, $s3
$s1=$s2+$s3

sub

sub $s1, $s2, $s3    
$s1=$s2$s3

addi

addi $s1, $s2, num
$s1=$s2+num

データ転送

load命令とstore命令がある。

  • load命令 : 主記憶かrレジスタに値を転送する
  • store命令 : レジスタから主記憶に値を転送する

lw

lw $s1, num($s2)
$s1=[$s2+num]

sw

sw $s1, num($s2)
$s1=[$s2+num]

論理演算

and

and $s1, $s2, $s3
$s1=$s2&$s3

or

nor $s1, $s2, $s3
$s1=$s2||$s3

nor

nor $s1, $s2, $s3
$s1=!($s2||$s3)

sll

sll $s1, $s2, 10
$s1=$s2<<10

sli

sli $s1, $s2, 10
$s1=$s2>>10

無条件ジャンプ

j

j 2500     意味 : go to 2500

MIPSのフィールド

op rs rt rd shamt funct
6bit 5bit 5bit 5bit 5bit 6bit
  • OP : 命令の基本操作。オペコード
  • rs : 第1のソース・オペランドのレジスタ
  • rt : 第2のソース・オペランドのレジスタ
  • rd : ディスティネーション・オペランドのレジスタ。結果を収める先
  • shamt : シフト量
  • funct : 機能コード。命令操作フィールドのバリエーションを表す。

実際のプログラム例

assing.asm

assign.c
int src = 1234;
int dst;

int main()
{
    dst = src;

    return 0;
}

これをMIPSのコードにコンパイルすると

assign.asm
# データ領域の宣言
        .data

# int src = 1234
        .globl    src
src:    .word     1234

# int dst
        .globl    dst
dst:    .word     0

#データ領域の宣言の終了
        .text

# int main ()
        .globl    main
main:

# dst = src;
        la    $t0, src     # srcのアドレス値をt0にロードする
        lw    $s0, 0($t0)  # t0の内容をs0にロードする
        la    $t1, dst     # dstのアドレス値をt1にロードする
        sw    $s0, 0($t1)  # s0の内容をt1にストアする

#return 0
        li    $v0, 0    # $v0に値9をロードする
        jr    $ra       # 呼び出しもとに戻る

addition.asm

addition.c
int x1 = 1234;
int x2 = 5678;
int y;

int main()
{
    y = x1 + x2;

    return 0;
}

これをMIPSのコードにコンパイルすると

addition.asm
# データ領域開始の宣言
        .data

# int x1 = 1234
        .globl    x1
x1:     .word     1234

# int x2 = 5678
        .globl    x2
x2:     .word     5678

# int y
        .globl    y
y:      .word     0

#テキスト領域の開始
        .text

# int main
        .globl    main
main:

# y = x1 + x2
    la    $t0, x1    
    lw    $s0, 0($t0)
    la    $t0, x2
    lw    $s1, 0($t0)
    add   $s0, $s0, $s1
    la    $t0, y
    sw    $s0, 0($t0)

# return 0
    li    $v0, 0
    jr    $ra

addition2.asm

addition2.caddition.cとほぼ変わらないが、初期値宣言をしていない。

addition2.c
int p;
int q;
int r;

int main()
{
    p = 1;
    q = 2;
    r = p + q;

    return 0;
}

これをコンパイルすると

addition2.asm
# データ領域の開始の宣言
        .data

# int p
        .globl    p
p:      .word     0

# int q
        .globl    q
q:      .word     0

# int r
        .globl    r
r:      .word     0

# テキスト領域の開始の宣言
        .text

# int main
        .globl    main
main:

# p = 1
    la    $t0, p
    li    $s0, 1
    sw    $s0, 0($t0)

# q = 2
    la    $t0, q
    li    $s0, 2
    sw    $s0, 0($t0)

# r = p + q
    la    $t0, p
    lw    $s0, 0($t0)
    la    $t0, q
    lw    $s1, 0($t0)
    add   $s0, $s0, $s1
    la    $t0, r
    sw    $s0, 0($t0)

# return 0
    li    $v0, 0
    jr    $ra

addition2.asmaddition.asmを比較してみると初期値宣言をしているaddition.asmの方が効率が良いことが分かる。

関連記事

0
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
twrcd1227
海外旅行とカメラが趣味です。
この記事は以下の記事からリンクされています
twrcd1227MIPSアセンブリ言語入門4からリンク
twrcd1227MIPSアセンブリ言語入門3からリンク
twrcd1227MIPSアセンブリ言語入門2からリンク

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
Azure AIを活用した機械学習に関する記事を投稿しよう!
~
フロントエンド強化月間 - 開発する上で知っておくべき知見を共有しよう
~