法政大学国際文化学部

情報システム概論

担当 重定 如彦

20081021

 

5回 機械語とアセンブラ言語

1.      機械語とアセンブラ言語

前回の授業で、CPUが機械語と呼ばれる言語によって記述されたプログラムによって動いていると説明しました。今回の授業では、機械語についてより具体的に説明します。

機械語の命令は前回の授業で述べたように、一つ一つの命令が数字で表現されますが、この数字と命令の対応を人間が覚えるのは非常に大変です。また、例え覚えられたとしても、その数字を人間が一つ一つ並べてプログラムを作ることは非常に大変です。

そこで、実際の機械語のプログラミングでは、アセンブラ言語と呼ばれる、機械語の命令を数字ではなくアルファベットで表現するという、機械語よりも人間が扱いやすい言語を使って行います。アセンブラ言語は機械語の命令の種類を表す「命令コード(又はオプコード)」と、命令の操作の対象となるデータを表わす「オペランド」の2種類の文字列で機械語の命令を表現します。例えば、足し算を行う機械語命令の命令コードを「ADD」、汎用レジスタのオペランドを「GR(general registerの頭文字)」と表現する場合、

   ADD GR, 2000

と記述することで汎用レジスタの値にメモリの2000番地の内容を足すという機械語の命令を表現することができます。機械語命令はそれぞれ記述するオペランドの数が決まっており、その数をとって「○オペランド命令」(○には必要なオペランドの数が入ります)または「○アドレス命令」と呼びます。例えばADD命令は2つのオペランドで指定された数を加算する命令なので2オペランド命令です。一般的なアセンブラ言語には0オペランド命令、1オペランド命令、2オペランド命令、3オペランド命令があります。

アセンブラ言語で記述されたプログラムはそのままでは実行できず、翻訳プログラムによって機械語に翻訳されてはじめて実行することができます。この翻訳の操作のことを
アセンブルと呼びます。アセンブラ言語で記述された命令と実際の機械語の命令は1対1に対応しており、アセンブルを行うプログラムは、アセンブラ言語で記述されたプログラムの行を一つ一つ対応する機械語に直すという作業を行います。

ポイント

·           コンピュータ(CPU)は機械語しか理解できない。

·           しかし人間が機械語でプログラムを書くのは非常に大変。

·           機械語の命令と1対1に対応する、人間が扱いやすいアセンブラという言語が作られ、人間はアセンブラ言語でプログラムを記述する。

·           アセンブラ言語で記述したプログラムは別の翻訳プログラムでアセンブルされ、CPUが理解できる機械語に翻訳される。

·           実際に実行されるのは、アセンブルされて作られた機械語の命令である。

機械語のプログラムの作成、実行の手順

(注:機械語の数値(16進数)は適当な値で、実際のものとは異なります)

 

 

2.      CASLとCOMET

機械語とアセンブラ言語はコンピュータのCPUの種類によって異なります。授業ではアセンブラ言語の勉強を目的として作られたCOMETという仮想的なCPUと、COMETのアセンブラ言語であるCASLについて解説します。COMETは機械語の学習に必要とされる基本的な機械語命令を備えおり、COMETのアセンブラ言語であるCASLは実際の情報処理技術者試験で出題されるアセンブラ言語の一つとして採用されていました(現在ではバージョンアップしたCOMETUが使われているようです)。

実際のCOMETを搭載したCPUを一人一人用意することはできませんので、授業ではWindows上で動作するCOMETの動作をシミュレートする「COMETシミュレータ」と、CASLで記述されたアセンブリ言語をCOMETの機械語に翻訳する「CASLエディタ/アセンブラ」というアプリケーションを使用します。

3.      COMETの仕様

アセンブラ言語の解説を行う前に、COMETのCPUの仕様について説明します。

·           メモリ

COMETのメモリのアドレス空間(アドレスの番地の範囲のこと)は16ビットであり、16進数で(0000)16〜(FFFF)16、10進数で0〜65535で表されます。また、一つのアドレスには16ビットのデータを格納することができます。

·           レジスタ

機械語のプログラムで制御することのできるレジスタには、汎用レジスタ、プログラムカウンタ、フラグレジスタがあります。汎用レジスタは16ビットのデータを格納できるレジスタが5つ用意されており、それぞれGR0〜GR4と表現します。プログラムカウンタはメモリのアドレスを表す16ビットのデータを格納できるレジスタでPCと表現します。フラグレジスタは演算の結果を表す2ビットのデータを格納できるレジスタでFRflag register)と表現します。

表記

名前

ビット数

意味

GR0〜GR5

汎用レジスタ

16

任意の用途に使用可能なレジスタ

PC

プログラムカウンタ

16

次に実行する機械語の命令のメモリのアドレスを指すレジスタ

FR

フラグレジスタ

演算の結果を表すレジスタ

 

 

演算結果

負の値

正の値

FRの値

(10)

(01)

(00)

·           数値

COMETが扱う数値は一番左のビットが符号を表す16ビットの固定小数点数であり、負の数は2の補数で表現されます。2の補数とは以下の方法で負の数を表す方法のことです。

Ø  数の絶対値(符号をとりはらったもの)を計算しそれを16ビットの2進数に直す。

Ø  各ビットの数字を反転させる。

Ø  1を加える。

例えば −100 を16ビットの2の補数で表すには、まず−100の絶対値である100を2進数になおします。  100=(0000000001100100)

次に、この各ビットを反転させると   (1111111110011011)

最後にこれに1を足すと        (1111111110011100)

となり、これが−100を16ビットの2の補数で表現した値です。

2の補数が使われる理由は2つあり、一つは負の数をビットを反転させて表したほうが演算回路を作りやすいからです。もう一つはビットを反転させただけでは0を

  (0000000000000000)  

  (1111111111111111)

 の2種類の方法で表すことができてしまいます。同じ数字を2種類の方法で表現することは、なにかと不都合がおきるのでそれを避けるために最後に1を足します。なお、2の補数で表現された負の数の絶対値を求める(正に直す)には全く同じ作業を行えばOKです。

最後の「1を加える」という作業を行わないものを「1の補数」と呼びます。

·           制御方式

COMETでは、一つの機械語命令が32ビット(メモリのアドレス2つ分)で表現され、プログラムは逐次方式(機械語の命令を記述されているアドレスの番地の順に実行する方式のこと)で実行されます。従って一つの機械語命令が実行されるとPCに1ではなく、2が加算されます。機械語の命令の種類については、後述します。

4.      CASLの仕様

CASLは、一行に一つの機械語命令を記述するという方式で記述します。各行は以下の形式で命令を記述します(下記は3オペランド命令の場合の記述例)。

 

ラベル 命令コード オペランド1, オペランド2, オペランド3 注釈

それぞれの意味は後述しますが、ラベル、命令、オペランド、注釈の間は少なくとも1文字以上の空白(半角のスペース記号)で区切り、オペランドを複数記述する場合はオペランドとオペランドの間を,半角のコンマ記号)で区切ります。

·           ラベル

ラベルは、その行の命令が格納されるメモリのアドレスを表す(最大6文字の)半角のアルファベットの文字列です。ラベルを記述すると、プログラムが機械語に翻訳され実際のメモリに格納されたときに、その行の命令が格納されるメモリのアドレスをラベルの名前を使って参照することができるようになります。

ラベルは必ずしも記述する必要はありませんが、ラベルを記述しない場合は必ず命令コードの前に一つ以上の空白記号を記述する必要があるので注意して下さい。ラベルの使い方については後述します。

·           命令コード

命令コードは、機械語の命令の種類を表すアルファベットの文字列です。命令コードの種類については後述します。命令コードは必ず半角の大文字で記述する必要があります。

·           オペランド

オペランドは命令コードによって指定された命令が計算に使用する為のデータを表します。オペランドは、命令コードの種類によって記述する数が異なり、複数記述する必要がある場合はオペランドとオペランドの間を,で区切ります。オペランドの部分に数値を記述する場合は、10進数と16進数の2種類の方法で記述することができます。10進数の場合は−32768〜32767の範囲のデータを記述でき、16進数の場合は数値の一番先頭に#記号を記述し、(0000)16〜(FFFF)16の範囲の数値を記述できます。

例:   1234 は10進数の1234   

#1234 は16進数の1234

またオペランドの部分にアドレスを記述する場合は、ラベルを使うことができます。

·           注釈

注釈の部分にプログラムの注釈を記述することができます。注釈は必ず ; (半角のセミコロン)の後に記述し、その行の;より後の部分はプログラムの実行に全く影響を及ぼしません。注釈は必ずしも各行に記述する必要はありませんが、プログラムを他人に説明したり、後からプログラムを見直したりする場合に非常に役に立つので、必要に応じて記述すると良いでしょう。また、例外として注釈だけの行を書くこともできます。その場合は、行の先頭に ; を書いてその右に注釈の文章を書くことができます。

5.      CASLエディタの使い方

·           CASLエディタの実行とエディタウィンドウの開き方

CASLエディタを使うには、「マイコンピュータ」→「Hドライブ」→「yamamoto」の順でフォルダのアイコンをダブルクリックし、その中の「casl.exeへのショートカット」を実行して下さい。CASLエディタのウィンドウが表示されるので、新しいプログラムを作成する場合には、メニューの「ファイル」→「新規作成」、既に作成したCASLのプログラムを読み込む場合はメニューの「ファイル」→「開く」を実行します。

注:授業で使用するCASLエディタはフリーソフトではありませんが、授業の目的で不特定多数の生徒にこのような形で使うということに関しては許可を取っています。

·           プログラムの編集方法

上記の操作を行うとCASLの中にプログラムを編集するためのエディタのウィンドウが開くので、この中にCASLのアセンブラのプログラムを記述します。このエディタの使い方ですが、プログラムの編集方法は、基本的にはメモ帳と変わりありません。

·           プログラムの書き方

プログラムは1行に1つの命令を前述の形式で記述します。このとき、ラベル(網掛け)命令コード(太字)、オペランドはそれぞれ縦方向に位置を揃えて書くとプログラムが見やすくなります。以下に揃えた場合とそうでない場合のプログラム例を挙げます。

揃えた場合

揃えなかった場合

              START

              LD                     GR1, A

              ADD                 GR1, B

              ST                     GR1, C

              EXIT

           DC                    

           DC                    

           DS                    

              END

START

LD   GR1, A

ADD GR1, B

ST   GR1, C

EXIT

 DC 8

 DC 5

 DS 1

END

上記のように揃えたほうが、どれがラベルでどれが命令コードか非常にわかりやすくなります。プログラムを書く際には左のプログラムのように揃えて記述することでプログラムのエラーを少なくしたり、エラーが発生した場合でもエラーの場所が発見しやすくなりますので、皆さんもプログラムを書く際には必ず揃えて書くようにして下さい。

縦方向に揃える方法ですが、スペースキーを押して空白記号を使って揃えるという方法もありますが、TABキーを使う方法をお勧めします。TABキーを押すことで、自動的にカーソルを8の倍数文字目の位置に移動させることができるからです。

·           プログラムの保存方法

作成したプログラムをファイルに保存するには、メニューの「ファイル」→「上書き保存」を実行するか、ツールバーの「保存」ボタンを押します。保存の方法に関しては他のWindowsアプリケーションと同じです。保存されたファイルの拡張子は .cas です。

·           アセンブルの方法

入力したプログラムをアセンブルするには、メニューの「ファイル」→「アセンブル」を実行するか、ツールバーの中にある「アセンブル」ボタンを押します。もしプログラムのファイルの保存をまだ行っていなければ保存を促すパネルが表示されるのでまずファイルを保存して下さい。もし入力したプログラムに文法的なエラーがなければ、正しくアセンブルできましたという内容のパネルが表示されます。ここで、パネルの「はい」というボタンを押すと「COMET」が起動されアセンブルの作業によって作成された機械語のプログラムを実行します。COMETについては後述します。

アセンブルを実行すると「CASL」の中に「アセンブル結果」という名前のウィンドウが表示され、この中にアセンブルの結果作成された機械語のプログラムや、もしエラーがあればエラー情報が表示されます。機械語のプログラムの部分では左にどの番地にどういう機械語の命令が記述されているか、右に対応するアセンブラ命令が表示されます。

·           エラーについて

入力したプログラムに文法的なエラーがあった場合、アセンブルを行うとエラーメッセージが表示されます。代表的なエラーとその対処方法について説明します。

エラー名

意味

対処方法例

Illegal Instruction

不正な命令コード

命令コードの部分に、「綴りミス」、「小文字」、「全角文字」がないかを調べる

Duplicated Label

ラベルの重複

同じラベル名が重複していないかを調べる

Illegal Label

ラベル名が不正

ラベルの文字数が7文字以上ではないか、またラベルに全角文字を使ってないかを調べる

Illegal Operand in GR Field

GRの部分が不正

オペランドの汎用レジスタの指定でGR0〜GR4以外を指定していないかを調べる

Too Many Operands

オペランド数が不正

オペランドの数が多すぎないかを調べる

Syntax Error

文法エラー

文法が間違っていないかを調べる

エラーが発生した場合は、アセンブル結果のウィンドウにエラーが起きた場所とエラー名が表示されるので、エラーメッセージを参考にして訂正しアセンブルしなおして下さい。

6.      命令コード(その1)

CASLの命令コードのうち、今回の授業で使うものについて説明します。なお、以下の説明で各命令の記述方法の説明では、オペランドの部分に以下の記号を使います。

 

記号

意味

実際の記述

GR

汎用レジスタを表す

GR0〜GR4のいずれか

adr

メモリのアドレスを表す

ラベルまたは、数値

 

·           ロード(Load)、ストア(Store)命令

ロード命令はメモリの内容を汎用レジスタに読み込む命令です。ロード命令は

 

命令コード

オペランド

LD

GR, adr

 

 

 

と記述し、adrで指定されたメモリのアドレスの内容がGRで指定された汎用レジスタに読み込まれます。例えば

   LD   GR1, 1000

というプログラムは、メモリの1000番地の内容を汎用レジスタ1(GR1)に読み込みむという動作を行います。

一方、ストア命令はロード命令の逆で、GRで指定した汎用レジスタの内容をadrで指定したメモリに書き込みます。ストア命令は以下のように記述します。

 

命令コード

オペランド

ST

GR, adr

 

ロード命令とストア命令は、行う作業は正反対ですが、いずれもオペランドの部分には先に汎用レジスタ名を書くという点に注意して下さい。また、COMETの命令のほとんどはロード命令やストア命令のように、1つ目のオペランドに汎用レジスタ2つ目のオペランドにメモリのアドレスを記述することになっています。従って、COMETでは、メモリのアドレスAの内容をアドレスBにコピーしたい場合は、一旦ロード命令でアドレスAの内容を汎用レジスタに読み込んでからその汎用レジスタの内容をアドレスBにストア命令で書き込むという作業を行う必要がある点に注意して下さい。

 

·           演算命令

演算命令は、汎用レジスタの内容とメモリの内容を演算する為の命令で、演算結果は計算に使った汎用レジスタに格納されます。また、演算結果によって、フラグレジスタ   (FR)の内容が変化します。演算命令には以下の5種類があります。

命令

命令コード

オペランド

意味

加算

ADD

GR, adr

足し算を行う

減算

SUB

GR, adr

引き算を行う

論理積

AND

GR, adr

AND演算を行う

論理和

OR

GR, adr

OR演算を行う

排他的論理和

EOR

GR, adr

EOR演算を行う

注意して欲しいのは、演算結果は必ず汎用レジスタのほうに反映されるということと、減算の場合は汎用レジスタの内容からメモリのアドレスを引き算するという点です。

また、排他的論理和という論理演算は、以下の表のようにいずれか片方だけが1の場合のみ1を返すという論理演算のことです。

EOR演算

COMETでは乗算や除算を行う機械語命令はありません。また、浮動小数点数で表現された数値の演算を行う機械語も用意されていません。これはCOMETが入門用のCPUであるためで、実際にはそれらの演算を行う機械語命令を備えているCPUもあります。

·           擬似命令

擬似命令とは、プログラムの開始場所を指定したり、メモリの中にデータを埋め込んだりするための命令のことで以下の5種類があります。擬似命令に対応する機械語命令が存在しないことから、「擬似」命令と呼びます(厳密にはEXITは擬似命令ではなくマクロ命令という種類の命令ですが、混乱を避けるためにここでは説明しません)

命令コード

オペランド

意味

START

(実行開始番地)

プログラムの先頭の定義

END

なし

プログラムの終わりの定義

DC

数値

そのメモリのアドレスに数値をデータとして埋め込む

DS

数値

数値で指定した数だけ、メモリの領域を確保する

EXIT

なし

プログラムをそこで終了させる

Ø  START
STARTはプログラムの先頭を表す擬似命令で、必ずプログラムの最初にこれを記述する必要があります。実行開始番地の部分にアドレスを記述すると、指定した番地からプログラムが実行されます。実行開始番地を省略した場合、STARTの次の行からプログラムが開始されます。

Ø  END
プログラムの終わりを表し、最後の行に必ずENDを記述する必要があります。

Ø  DC
DCが記述されている部分のメモリに、数値をデータとして埋め込みます。
DCの行にラベルをつけることで、その行のメモリのアドレスをラベルの名前を使って参照することができます。

Ø  DS
数値で記述した分だけ、計算結果などのデータを格納するためのアドレスをメモリの中に確保します。DSの行にラベルをつけることで、確保したメモリの先頭アドレスをラベルで参照することができます。

Ø  EXIT
プログラムをそこで終了させるという意味を持ちます。ENDと異なり、プログラムの途中の好きな場所に記述することができます。

7.      サンプルプログラム

ここまでの説明ではおそらくわからない方が大半だと思いますので、実際にプログラムの例を挙げて解説します。例として、先ほどのプログラムの書き方のところで例としてあげた下記のプログラムの解説をします。なお、下記では説明を行う為に、それぞれの行の一番左に行の番号をつけています。実際のプログラムにはこの行番号は記述しません

                                       START

                                       LD                     GR1, A

                                       ADD                  GR1, B

                                       ST                     GR1, C

                                       EXIT

                                    DC                    

                                    DC                    

                                    DS                    

このプログラムは、メモリのA番地の内容(=8)とメモリのB番地の内容(=5)を足し算し、メモリのC番地に格納するという意味を持ちます。順を追って説明します。

                                       END

 

·           アセンブル

まず、アセンブルによってそれぞれの行の内容が機械語に翻訳されて、メモリに格納されます。この時、DC命令が記述されている行では、オペランドで記述されている数値がそのままメモリの内容となります。DC命令は主にプログラムの計算で使われるデータをメモリに格納するという用途で使われ、このプログラムでは、6行目と7行目で、DC命令によって足し算を行う為のデータである「8」と「5」をメモリに格納します。

実際には、6行目で8という数値が、7行目で5という数値がメモリに格納されます。6行目にはAというラベルがついているので、6行目で8を格納したメモリのアドレスをAというラベル名を使って参照することができます。同様に、7行目の5というデータを格納したメモリはBというラベル名を使って参照することができます。

DS命令は、計算結果などを格納するメモリを確保するために使われます。この例では結果は1つなのでDSのオペランドには1を記述しその結果、計算結果を格納するためのアドレスが一つ用意されます。8行目のDSにはCという名前のラベルがついているので、このメモリのアドレスはCというラベル名を使って参照することができます。以下に、アセンブルを行った直後のレジスタとメモリの中身を記述します。

 

汎用レジスタ1

 

メモリのA番地

メモリのB番地

メモリのC番地

 

 

·           プログラムの実行

次に、プログラムを順に辿っていきます。1行目はプログラムの先頭を表す擬似命令であるSTARTが記述されています。STARTは必ず最初に記述する決まりになっているのでこの行はそれ以外に特に意味はありません。同様に最後の9行目にもプログラムの終了を表すENDが記述されています。

次に2行目の命令が実行されます。2行目にはロード命令であるLDが記述されており、オペランドには「GR1」とラベルの「A」が記述されています。GR1は、汎用レジスタ1を表しており、「A」は6行目で8というデータを格納したメモリのアドレスを表しています。従って、2行目の命令では、「A」のアドレスの中身、すなわち8という数字を汎用レジスタGR1に読み込むという動作を行います。灰色の部分がこの命令で使われたレジスタとメモリです。

 

汎用レジスタ1

 

メモリのA番地

メモリのB番地

メモリのC番地

 

 

 

 

次に3行目の命令を実行します。3行目には、加算命令であるADDが記述されており、オペランドには「GR1」とラベルの「B」が記述されています。従って、この行では、汎用レジスタ1の内容とメモリのBの内容を加算して結果を汎用レジスタ1に代入するという意味を持ちます。従って8+5=13なので、汎用レジスタの中身が13に変化します。

 

汎用レジスタ1

 

メモリのA番地

メモリのB番地

メモリのC番地

13

 

 

次の4行目では、ストア命令であるSTが記述されており、汎用レジスタ1の内容がメモリのC番地に書き込まれます。従って、4行目の実行が終了した時点で、メモリのC番地にメモリのA番地とメモリのB番地の内容を足し算した結果の13が格納されることになります。

 

汎用レジスタ1

 

メモリのA番地

メモリのB番地

メモリのC番地

13

 

13

 

最後の5行目にはEXITというプログラムの実行をここで終了させるという意味の擬似命令が記述されているので、ここでプログラムは終了します。ここで、EXITを記述し忘れると、次の6行目のデータを機械語の命令として実行してしまうので、このEXITは必ず書く必要がある点に注意して下さい。

8.      COMETの使い方

アセンブルがうまくいった場合は、「COMETで実行しますか?」というパネルが表示されるので、ここで「はい」と答えて下さい。すると作成した機械語のプログラムを実行するシミュレータであるCOMETというプログラムが実行され、新しいウィンドウが表示されます。COMETの詳しい使い方は次回の授業で行いますが、このウィンドウの左にはメモリの内容、右にはレジスタの内容が表示されます。「メモリ」の内容の部分ですが、左から右にむかって、(0000)16番地から順番にメモリの内容が16進数で表示されます。また、これから実行する機械語命令が格納されているアドレスが赤く反転表示され、一つ前に実行された機械語命令が格納されたアドレスが青色で反転表示されます。緑色で反転している部分はカーソルを意味し、マウスのクリックで位置を変更可能です。メモリの表示部分はツールバーの「リスト表示」ボタンを押すことで表示形式を変えることができます。リスト表示では一行に2つのアドレスの内容とそれをアセンブラになおした場合のデータが表示されます(注:ニーモニックとは命令コードのこと)。

右にある「CPUレジスタ」の下にはCPUの各レジスタの内容の一覧が16進数で表示されます。この中で「命令」の右には次に実行される命令の機械語のコードと対応するアセンブラの名前が記述されています。また、「直前の状態」の下に記述されている内容は、現在の機械語命令が実行される直前のレジスタの状態を表しています。

なお、ウィンドウの中のスタックと書かれている部分と、CPUレジスタの中で、MRとSPと書かれている部分は本授業では使いませんので無視して下さい。

プログラムを実行するには、ツールバーの右にある「最初から実行」ボタンを押します。すると機械語の命令が先頭(アドレスの0番地)から順番に実行されます。最初から実行ボタンは、プログラムを最初から最後まで一気に実行してしまいますが、その右にある「1ステップ実行」は、一つの命令を実行するとそこで止まります。1ステップ実行を使うことで機械語の命令がどのような影響を及ぼすかを一つ一つ辿ることが出来ます。

アセンブラの中でラベルが実際のアドレスの何番地であるかを知るには、CASLのアセンブル結果を参照して下さい。ウィンドウの中で知りたいラベルが記述されている行の「番地」と書かれている列の内容がラベルの具体的な番地(16進数)です。先ほどのサンプルプログラムの場合、ラベルAは(0008)16番地、ラベルBは(0009)16番地、ラベルCは(000A)16番地であることを確認して下さい。

1ステップ実行を使い、先ほどのプログラムの汎用レジスタ1(GR1)の内容とメモリのC番地である(000A)16番地の内容が機械語の命令の実行によって先ほどのサンプルプログラムで解説したとおりに変更する様子を実際に確かめてみて下さい。

9.      課題

以下のプログラムを作り実行せよ。作成したプログラムをGドライブにkadai1.casという名前で保存し、ta080017@mail.edu.i.hosei.ac.jp課題のメールとして添付ファイルで送ること。

 

DC命令を使ってメモリのA番地に10、B番地に5、C番地に3という数字を格納し、

 

A番地の内容 + B番地の内容 ― C番地の内容 

 

を計算し、結果を DS命令を使って確保した D番地に 計算結果を格納せよ。なお、ここでいうA,B,C,Dはプログラムのラベルの名前のことを意味する。

ヒント:A番地とB番地の内容の足し算は今日の例題と全く同じ方法で行うことができる。足し算を行ったあと同様の方法で SUB 命令を使えば引き算を行える。計算した結果をD番地に格納する方法も今日の例題と同じ方法で行うことが出来る。

 
出席、課題のメールはta080017@mail.edu.i.hosei.ac.jpにお願いします。

質問のメールなどは、sigesada@.hosei.ac.jpまでお願いします。

授業の資料の最新版はhttp://www.edu.i.hosei.ac.jp/~sigesada/にあります。