[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

コンピュータIIL(情報科学入門)第5回

目次 索引
5.1 計算機の構成(2)
5.2 演習5
5.3 レポート課題

5.1 計算機の構成(2)

h2 機械語 toc-machine-languages

h3 スタック toc-stacks

前回、スタックを特別な変数である思ってくださいと言いました。
本当は、
index スタック stack すたつく
は複数のデータが格納できるデータ構造です。
スタックには次々とデータが格納できますが、
取り出せるのは最後に格納したデータのみです。

机の上に雑誌を積み上げる様子を考えてください。
例えば、4 月号の上に 5 月号をのせ、その上に 6 月号をのせます。
直接取り出せるのは 6 月号のみです。
6 月号を取り除けば、5 月号が取り出せます。
5 月号も取り除き、7 月号をのせ、その上に 8 月号をのせます。
すると、8 月号、7 月号、4 月号の順に取り出せます。
スタックはこのようなイメージのものです。

スタックにデータを格納することを、
index プッシュ push ふつしゆ
と言います。
スタックからデータを取り出すことを、
index ポップ pop ほつふ
と言います。
スタックは、最後に格納したデータが最初に取り出されます。
この仕組みを、
index 後入れ先出し last-in first-out あといれさきたし
と呼びます。

雑誌の積み上げは上に伸びますが、
ここでは右に伸びるようにスタックを表現します。
今、空のスタックに 4 をプッシュしますと、
スタックの値は {4} になります。
さらに 5 をプッシュし、6 をプッシュしますと、
スタックの値は {4, 5, 6} になります。
次に、ポップしますと 6 が取り出せ、
スタックの値は {4, 5} になります。
さらにポップしますと 5 が取り出せ、
スタックの値は {4} になります。
続いて 7 をプッシュし、8 をプッシュしますと、
スタックの値は {4, 7, 8} になります。
最後に 3 回ポップしますと、8, 7, 4 の順に取り出せ、
スタックの値は {} になります。

Java 仮想マシンには四則演算の機能がありますが、
この演算は、スタックの右端のデータに対して行われます。
例えば、9 - 6 を計算したい場合、
9 と 6 をスタックにプッシュしてから引き算の命令を実行します。
すると、計算された 9 と 6 はポップされ、
計算結果 3 がプッシュされます。
スタックの値で言いますと、
{9, 6} のときに引き算の命令を実行しますと、
{3} になります。

h3 命令の形式 toc-instruction-formats

一般的に、命令は前半部分と後半部分に分かれます。
前半は、命令の種類を表す部分で、
index オペレーション・コード operation code おへれえしよんこおと
または
index オペコード opcode おへこおと
と呼ばれます。
後半は、命令の付加データを表す部分で、
index オペランド operand おへらんと
と呼ばれます。
命令によっては、オペランドのないものもあります。

たとえば、整数 9 をスタックにプッシュする命令 1009 では、
オペコードは 10, オペランドは 09 です。

h3 アセンブラ toc-assemblers

プログラムは命令の系列ですが、
これを、コンピュータが直接理解できる言語という意味で、
index 機械語 machine language きかいこ
と呼ぶことがあります。
機械語は 16 進数の系列であり、
人間にとって分かりにくいものです。

少しでも分かりやすくするために、アセンブリ言語が考えられました。
index アセンブリ言語 assembly language あせんふりけんこ
とは、命令に覚えやすい文字列 (英単語など) を対応させた言語です。
特に、オペコードに対応する文字列を
index ニーモニック・コード mnemonic code にいもにつくこおと
と呼びます。

例えば、命令 1009 はアセンブリ言語では bipush 9 となります。
bipush は、Byte Integer PUSH という意味のニーモニック・コードです。

アセンブリ言語を機械語に置き換えることを、
index アセンブル assemble あせんふる
と言います。
アセンブルを行うソフトウェアを、
index アセンブラ assembler あせんふら
と呼びます。
逆に、機械語をアセンブリ言語に置き換えることを、
index 逆アセンブル disassemble きやくあせんふる
と言います。

h3 逆アセンブルの例 disassemble-examples

今日扱う命令は次の通りです。

ニーモニック 命令長   第 1 第 2  命令
nop          1 バイト 0x00       何もしない。
iconst_0     1 バイト 0x03       整数 0 をスタックにプッシュする。
iconst_1     1 バイト 0x04       整数 1 をスタックにプッシュする。
bipush       2 バイト 0x10 byte  整数 byte をスタックにプッシュする。
iload        2 バイト 0x15 index 第 index 変数の値をスタックにプッシュする。
iload_1      1 バイト 0x1b       第 1 変数の値をスタックにプッシュする。
iload_2      1 バイト 0x1c       第 2 変数の値をスタックにプッシュする。
istore       2 バイト 0x36 index スタックからポップした値を第 index 変数に格納する。
istore_1     1 バイト 0x3c       スタックからポップした値を第 1 変数に格納する。
istore_2     1 バイト 0x3d       スタックからポップした値を第 2 変数に格納する。
iadd         1 バイト 0x60       整数の足し算を行う。
isub         1 バイト 0x64       整数の引き算を行う。
imul         1 バイト 0x68       整数の掛け算を行う。
idiv         1 バイト 0x6c       整数の割り算を行う。
irem         1 バイト 0x70       整数の剰余算を行う。

/*  1*/ class Ex5 {
/*  2*/     public static void main (String[] args) {
/*  3*/         int x;
/*  4*/         int y = 6;
/*  5*/         x = 9 - y;
/*  6*/         System.out.println(x);
/*  7*/     }
/*  8*/ }

b04a001@AsiaA1:~/comp2l% javac Ex5.java
b04a001@AsiaA1:~/comp2l% java Ex5
3
b04a001@AsiaA1:~/comp2l%

00000150: 0010 1006 3d10 091c 643c b200 021b b600  ....=...d<......

b04a001@AsiaA1:~/comp2l% javap -c Ex5
...
   0:   bipush  6
   2:   istore_2
   3:   bipush  9
   5:   iload_2
   6:   isub
   7:   istore_1
...
b04a001@AsiaA1:~/comp2l%

命令 bipush 6 でプッシュされ、スタックの値は {6} になります。
命令 istore_2 でポップされ、スタックの値は {} になり、第 2 変数の値は 6 になります。
命令 bipush 9 でプッシュされ、スタックの値は {9} になります。
命令 iload_2 で第 2 変数の値がプッシュされ、スタックの値は {9, 6} になります。
命令 isub で計算 9 - 6 = 3 が行われ、スタックの値は {3} になります。
命令 istore_1 でポップされ、スタックの値は {} になり、第 1 変数の値は 3 になります。
したがって、第 1 変数の値 3 が出力されます。

例題1.
プログラム 1007 3d1c 1003 6c3c を実行すると何が出力されるかを答えてください。
出力だけではなく、プログラムの動作についても説明してください。
バイナリ・ファイル Ex5.class のプログラムの部分を置き換え、
java コマンドを実行すると、答えが確認できます。

解答する前に、バイナリ・ファイル Ex5.class を次のように書き換え、
逆アセンブルします。

00000150: 0010 1007 3d1c 1003 6c3c b200 021b b600  ....=...l<......

b04a001@AsiaA1:~/comp2l% javap -c Ex5
...
   0:   bipush  7
   2:   istore_2
   3:   iload_2
   4:   bipush  3
   6:   idiv
   7:   istore_1
...
b04a001@AsiaA1:~/comp2l%

解答例1.
命令 bipush 7 でスタックの値は {7} になる。
命令 istore_2 でスタックの値は {} になり、第 2 変数の値は 7 になる。
命令 iload_2 でスタックの値は {7} になる。
命令 bipush 3 でスタックの値は {7, 3} になる。
命令 idiv で割り算 7 / 3 = 2 が行われ、スタックの値は {2} になる。
命令 istore_1 でスタックの値は {} になり、第 1 変数の値は 2 になる。
したがって、第 1 変数の値 2 が出力される。

確認のため、java コマンドを実行します。

b04a001@AsiaA1:~/comp2l% java Ex5
2
b04a001@AsiaA1:~/comp2l%

h2 演習

次のプログラムを実行すると何が出力されるかを答えてください。
出力だけではなく、プログラムの動作についても説明してください。
バイナリ・ファイル Ex5.class のプログラムの部分を置き換え、
java コマンドを実行すると、答えが確認できます。

  1. 1008 1002 6c3c 0000
  2. 1009 3d1c 1c68 3c00
  3. 0404 6004 6004 603c

5.2 演習5


5.3 レポート課題

今日の演習5の答案をkonishi@twcu.ac.jpあてにメールで送ってください。 メールには、学生番号、氏名、科目名、授業日(10月22日)を明記してください。


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2004年10月22日更新
konishi@twcu.ac.jp
Copyright (C) 2004 Zenjiro Konishi. All rights reserved.