コンテンツにスキップ

期末試験 2024#

答えの表示/非表示

時間:60分,問題:16問,配分:各6点(出席1点,コメント3点)
SCコードとJavaのバイトコードに関する補足資料あり

1. 論理型言語#

Prologに関する説明のうち,適切なものを全て列挙せよ.

  1. Prologは命令型言語の一種である
  2. Prologは宣言型言語の一種である
  3. Prologのプログラマは処理の手続きを記述する
  4. Prologの内部処理は単一化に基づく推論の繰り返しである
  5. Prologでは単一化に失敗した際に自動的にバックトラックが行われる
  6. Prologでは開発者による強制バックトラックが可能である

Exam-answer

2,4,5,6

以下はProlog処理系への質問の入力である.=演算子により左右2項の単一化を試みている.単一化に成功する処理の番号を全て列挙せよ.

?- 1 = 1.              % 1
?- 2 = 3.              % 2
?- X = 1.              % 3
?- X = A.              % 4
?- f(1) = f(1).        % 5
?- f(X) = g(X).        % 6
?- f(X, Y) = f(1, 3).  % 7
?- f(g(X)) = f(g(1)).  % 8

Exam-answer

1,3,4,5,7

以下はPrologプログラムである.最大公約数を表す述語gcd(A, B, X)の記述であり,これは整数値ABの最大公約数がXである,という関係を表す.A < Bとする.???の部分を埋めて述語gcd(A, B, X)を完成させよ.

gcd(0, B, B).
gcd(A, B, X) :- A > 0, R is B mod A, ???.

Exam-answer

gcd(R, A, X)

GMCの祖母という関係を表す述語grandmother(GM, C)の論理式を記述せよ.以下2つの述語を用いること.論理式のヘッドとボディの全てを記述すること.

  • child(C, P)CPの子供という関係を表す述語
  • female(F)Fが女であることを表す述語

Exam-answer

grandmother(GM, C) :- female(GM), child(GM, P), child(P, C).

2. C言語#

Cソースコードと等価なSCコードのペアを示す.各ペアについてSCコード内の???の部分を埋めよ.以下の点に注意すること.

  • ???は1行以上の複数行で構成される
  • 局所変数のベースポインタからの相対番地は,iを3,jを4とすること
  • SCコードの各行のアドレスは,数値ではなく記号番地(xy等)で表すこと
  • 最適化は禁止とする.例えばi = 10 + 20;i = 30;と解釈してはいけない

以下SCコードの???の部分を埋めよ.

// Cソースコード
void main() {
  int i;
  i = 10 + 20;
}
// SCコード
ENT 3
???
HLT

Exam-answer

LDC 10
LDC 20
BOP +
STL 3

以下SCコードの???の部分を埋めよ.

// Cソースコード
void main() {
  int i, j;
  j = 10;
  i = j;
}
// SCコード
ENT 4
???
HLT

Exam-answer

LDC 10
STL 4
LLD 4
STL 3

以下SCコードの???1の部分を埋めよ.

// Cソースコード
int f() {
  return 10;
}
void main() {
  int i;
  i = f();
}
// SCコード
   ENT 3  // main()
   ???1
   STL 3
   HLT
x: ENT 2  // f()
   LDC 10
   ???2

Exam-answer

LDC x
MST
CUP 0

Q7のSCコードの???2の部分を埋めよ.

Exam-answer

STL 0
RET 0

SCコードでは関数実行時にENT命令を用いて,戻り番地と動的リンクのメモリセルをスタック上に確保している.この2つのメモリセルの役割として最も適切なものを全て選択せよ.

  1. 大域変数用のデータ領域
  2. 関数呼び出し時の引数データの保持
  3. 関数終了後の元関数への復帰
  4. 関数終了後のレジスタ値の復元

Exam-answer

3

3. Java言語#

Javaソースコードと等価なJavaバイトコードのペアを示す.各ペアについてバイトコード内の???の部分を埋めよ.以下の点に注意すること.

  • ???は1行以上の複数行である
  • 局所変数のベースポインタからの相対番地はiを3とすること
  • バイトコードのアドレスは数値ではなく記号番地(xy等)で表すこと
  • 最適化は禁止とする.例えばi = 10 + 20;i = 30;と解釈してはいけない
  • int定数のプッシュ命令は値のサイズに依らず,常にbipush命令を使って良い
  • _を含むオペランドなしバイトコード命令は,_を含まない汎用命令で代用せよ(istore_0istore 0とすること)

以下バイトコードの???の部分を埋めよ.

// Javaソースコード
void main() {
  int i;
  i = 10 + 20;
}
// バイトコード
???
return

Exam-answer

bipush 10
bipush 20
iadd
istore 3

以下バイトコードの???の部分を埋めよ.

// Javaソースコード
void main() {
  int i;
  while (10 == 20) {
    i = 30;
  }
}
// バイトコード
x: bipush 10
   bipush 20
   ???
y: return

Exam-answer

if_icmpne y  // 条件が反転する点に注意
bipush    30
istore    3
goto      x

以下はあるインスタンスoのメソッドm()を呼び出すソースコードと,それに対応するバイトコードである.メソッドm()は一つの引数を受け取る.oの相対番地は3である.バイトコード命令invokevirtualがJVM上で行う処理として適切なものを全て選択せよ.

// Javaソースコード
o.m(10);
// バイトコード
aload         3
bipush        10
invokevirtual m
  1. スタック上の値の比較
  2. 局所変数の値のプッシュ
  3. 現在のレジスタ値の退避
  4. スタック最上部への引数の値のプッシュ
  5. m()用の新たなスタックフレーム領域の構築

Exam-answer

3,5

invokevirtualの前にaload命令を用いてインスタンスoの参照をスタックに積み上げる理由として,適切なものを全て選択せよ.

  1. om()内でのthisとして用いるため
  2. メモリ領域をスタック形式で利用するため
  3. 引数のサイズに応じて効率的にメモリを利用するため
  4. m()終了後に元スタックフレームを再構築するため

Exam-answer

1

以下はJavaによる局所変数の宣言と初期化である.各局所変数について,初期化された値自体がスタック領域・ヒープ領域・メソッド領域のどこに格納されるか,それぞれ答えよ.

int i       = 10;               // 1
int j       = list.size();      // 2
int a[]     = {1, 2, 3};        // 3
double d    = 3.14;             // 4
String s    = "test";           // 5
Exception e = new Exception();  // 6

Exam-answer

  • スタック:1,2,4
  • ヒープ:3,5,6,7

4. その他の言語(例外処理)#

以下のJavaメソッド宣言について,コンパイルエラーとなるメソッドの名前を全て列挙せよ.E1は検査例外,E2は非検査例外とする.

void f1() { throw new E1(); }
void f2() { throw new E2(); }
void f3() throws E1 { throw new E1(); }
void f4() throws E2 { throw new E2(); }
void f5() {
  try {
    throw new E1();
  } catch(E1 e) {}
}
void f6() {
  try {
    throw new E2();
  } catch(E2 e) {}
}

Exam-answer

f1()

以下はJavaを実行した際に発生したスタックトレースの内容である.null参照例外が発生していることが確認できる.null参照操作を直接的に行っている箇所のファイル名と行番号を答えよ.

ERROR!
Exception in thread "main" java.lang.NullPointerException:
    at Parser.parseInt(Parser.java:40)
    at Parser.parse(Parser.java:30)
    at Main.run(Main.java:20)
    at Main.main(Main.java:10)

Exam-answer

Parser.javaの40行目

補足資料#

SCコード命令一覧#

stack[]:スタック領域,sp:スタックポインタ,bs:ベースポインタ,pc:プログラムカウンタ

# SCコード 意味 スタック領域とレジスタに対する操作
1 LDC a load constant sp++; stack[sp]=a;
2 LLD a load local sp++; stack[sp]=stack[bs+a];
3 LGD a load global sp++; stack[sp]=stack[a];
4 LLA a load local addr sp++; stack[sp]=bs+a;
5 LGA a load global addr sp++; stack[sp]=a;
6 STL a store local stack[bs+a] =stack[sp]; sp--;
7 STG a store global stack[a] =stack[sp]; sp--;
8 STO store at indexed addr stack[stack[sp-1]]=stack[sp]; sp-=2;
9 IND a indexed fetch stack[sp] =stack[stack[sp]+a];
10 UJP L jump pc=L;
11 FJP L jump if false if(stack[sp]==0){pc=L; sp--;}
12 ENT a enter block sp=bs+a;
13 MST mark stack sp++; stack[sp]=base; sp++;
14 CUP a※1 call user procecure stack[sp-a]=pc+1; bs=sp-a-2; pc=stack[bs];
15 RET a※2 return from function sp=bs-a; pc=stack[bs+2]; bs=stack[bs+1];
16 BOP o※3 binary operation sp--; stack[sp]=(stack[sp])o(stack[sp+1]);
17 UOP o※4 unary operation stack[sp]=o(stack[sp]);
18 HLT halt EXIT

※1 aは呼び出す関数の引数の数
※2 関数の返り値がvoid型のときa=1,int型の時a=0
※3 oは二項演算子(+ - * / > >= < <= ==等)
※4 oは単行演算子(+ - !等)

Javaバイトコード命令一覧#

stack[]:スタック領域,heap[]:ヒープ領域,
optop:optopレジスタ(スタック最上部),frame:frameレジスタ(制御領域),
vars:varsレジスタ(スタック最下部),pc:pcレジスタ(プログラムカウンタ)

# 命令 スタック領域とレジスタに対する操作
1 bipush c optop++; stack[optop]=c;
2 ldc a optop++; stack[optop]=heap[a];
3 iload a optop++; stack[optop]=stack[vars+a];
4 aload a optop++; stack[optop]=stack[vars+a];
5 istore a stack[vars+a]=stack[optop]; optop--;
6 astore a stack[vars+a]=stack[optop]; optop--;
7 iadd optop--; stack[optop]=stack[optop]+stack[optop+1];
8 isub optop--; stack[optop]=stack[optop]-stack[optop+1];
9 goto L pc=L;
10 if_icmpne L if(stack[optop]!=stack[optop-1]){optop-=2; pc=L}
11 if_icmpeq L if(stack[optop]==stack[optop-1]){optop-=2; pc=L}
12 if_icmpge L if(stack[optop]>=stack[optop-1]){optop-=2; pc=L}
13 if_icmpgt L if(stack[optop]> stack[optop-1]){optop-=2; pc=L}
14 if_icmple L if(stack[optop]<=stack[optop-1]){optop-=2; pc=L}
15 if_icmplt L if(stack[optop]< stack[optop-1]){optop-=2; pc=L}
16 invokevirtual m※1 stack[optop+v+1]=pc;
stack[optop+v+2]=vars;
stack[optop+v+3]=frame;
vars =optop-p;
frame=optop+v+1;
optop=optop+v+4;
pc=m;

※1 vはメソッドm()の局所変数の数,pm()の引数の数