使用方法
interpreter.rb内最初のDEBUG_STEPをtrueにするとステップ(1命令毎)動作します。コンパイル方法 C:¥> ruby sscr.rb sample.src sample.asm アセンブリインタープリター実行方法 C:¥> ruby interpreter.rb sample.asm
ソースとサンプルsscr_003a.lzh
int add(a,b){ int x; x = a + b; return(x); } print add(a+1,b+2);
stmt : | stmt_return (追加) decl_int : 'INT' list_var ';' | 'INT' IDENT '(' list_var ')' '{' list_stmt '}' ';' (追加) stmt_return: 'RETURN' ';' (追加) | 'RETURN' expr ';' (追加) primary : IDENT | IDENT '(' list_exp ')' (追加)
adr アドレス (adr) アドレスadrのデータ R SP(p) or BP(bp) pc プログラムカウンタ p スタックポインタ(値が入っているトップを指す) s[p] pが示すスタックの値 bp ベースポインタ(スタック上の特定の位置を指す) ※spとbpの初期値は、スタックボトム-1である LDA offset[R] s[p+1]=R+offset,p=p+1 LEASP offset[R] p=R+offset exp) LEASP 1[SP] -> p=p+1 LEABP pffset[R] bp=R+offset PUSH sp[p+1]=bp,p=p+1 POP bp=sp[p],p=p-1 CALL adr sp[p+1]=pc+1(次命令アドレス),p=p+1 RET pc=sp[p],p=p-1
int foo(a,b){ int c,d; } foo(aa,bb); ------------------------------------ main内foo呼び出し直前 bp sp v v [n,n,n] foo開始時 bp sp v v [n,n,n,z,bb,aa,BP,ret,c,d] z :戻り値格納場所 aa,bb:arg BP :foo呼出前のBP位置 ret :return adr c,d :local var local_var/argアクセス arg1(aa) LDA -1[BP] arg2(bb) LDA -2[BP] local1(c) LDA 2[BP] local2(d) LDA 3[BP] ------------------------------------ call foo 手順 main v(BP0) [n,n,n] LEASP 1[SP] (sp=sp+1,戻値格納場所) [n,n,n,z] (push arg) (aa,bb) [n,n,n,z,bb,aa] PUSH [n,n,n,z,bb,aa,BP0] v(BP1) LEABP [SP] (bp=sp) [n,n,n,z,bb,aa,BP0] CALL foo (push ret_adr) [n,n,n,z,bb,aa,BP0,ret] foo LEASP 2[SP] (sp=sp+2,local_var数) [n,n,n,z,bb,aa,BP0,ret,c,d] LDA -3[BP] [n,n,n,z,bb,aa,BP0,ret,c,d,BP1-3] return foo 手順 foo v(BP1) [n,n,n,z,bb,aa,BP0,ret,c,d,BP1-3,v] STS ((BP-3)=ret_value) [n,n,n,v,bb,aa,BP0,ret,c,d,v] DEL [n,n,n,v,bb,aa,BP0,ret,c,d] LEASP 1[BP] (c,d) [n,n,n,v,bb,aa,BP0,ret] RET [n,n,n,v,bb,aa,BP0] main v(BP) POP [n,n,n,v,bb,aa] LEASP -2[SP](aa,bb) [n,n,n,v]
ソースとサンプルsscr_002.lzh
print [式,…];
stmt_print: 'PRINT' list_exp ';' list_exp : | expr ',' list_exp
ソースとサンプルはこちら
英小文字で始まる、小文字の英数字列(大文字は使用不可) [a-z][a-z0-9]*
int 変数[,変数,…]; if(条件) 文 if(条件) 文 else 文 while(条件) 文 条件:0(偽),0以外(真) print 変数[,変数,…]; input 変数; 式; {文 文…}
代入 = 比較 ==,!=,<=,<,>=,> :0(偽),1(真) 加減 +,- 乗除 *,/
program : list_stmt 'EOF' list_stmt: | stmt list_stmt stmt : decl_int | stmt_if | stmt_while | stmt_print | stmt_input | block | expr ';' | ';' decl_int : 'INT' list_var ';' stmt_if : 'IF' '(' expr ')' stmt | 'IF' '(' expr ')' stmt 'ELSE' stmt stmt_while: 'WHILE' '(' expr ')' stmt stmt_print: 'PRINT' list_var ';' stmt_input: 'INPUT' IDENT ';' block : '{' list_stmt '}' list_var : IDENT | IDENT ',' list_var expr : exp_asn | exp_comp exp_asn : IDENT '=' expr exp_comp : exp_add | exp_add '==' exp_add | exp_add '<=' exp_add | exp_add '>=' exp_add | exp_add '<' exp_add | exp_add '>' exp_add | exp_add '!=' exp_add exp_add : exp_mul | exp_mul '+' exp_add | exp_mul '-' exp_add exp_mul : primary | primary '*' exp_mul | primary '/' exp_mul primary : IDENT | '-' NUMBER | NUMBER | '(' expr ')'
adr アドレス (adr) アドレスadrのデータ pc プログラムカウンタ p スタックポインタ(値が入っているトップを指す) s[p] pが示すスタックの値 命令 NOP 無実行 ADD s[p-1]=s[p-1]+s[p], p=p-1 exp) [n,2,3]->[n,5] SUB s[p-1]=s[p-1]-s[p], p=p-1 MUL s[p-1]=s[p-1]*s[p], p=p-1 DIV s[p-1]=s[p-1]/s[p], p=p-1 CMPEQ if s[p-1]==s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 exp) [n,1,1]->[n,1] CMPNE if s[p-1]!=s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 exp) [n,1,1]->[n,0] CMPLE if s[p-1]<=s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 CMPLT if s[p-1]< s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 CMPGE if s[p-1]>=s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 CMPGT if s[p-1]> s[p] then s[p-1]=1 else s[p-1]=0, p=p-1 JP adr pc=adr JPT adr if s[p]!=0 then pc=adr, p=p-1 JPF adr if s[p]==0 then pc=adr, p=p-1 DEL p=p-1 LDS s[p]=(s[p]),p=p exp) [n,5]->[n,5番地のデータ] LDA adr s[p+1]=adr,p=p+1 exp) [n]->[n,adr] LDI dat s[p+1]=dat,p=p+1 exp) [n]->[n,dat] STS (s[p-1])=s[p],s[p-1]=s[p],p=p-1 exp) [n,adr,dat]->[n,dat] (adr番地)=dat ※datがスタック上に残ることに注意 PRT p=p-1 exp) [n,dat]->[n] PRINT dat INP s[p+1]=dat,p=p+1 exp) [n]->[n,dat] INPUT dat STOP 停止
-----source----- int a,b,c; a = 2; b = 3; if(a==0) print a; else{ c = a*(b+4); print c; } ---------------- -----asm出力---- _VAR _a$ INT 0 _b$ INT 0 _c$ INT 0 _END_VAR _PROG LDA _a$ LDI 2 STS DEL LDA _b$ LDI 3 STS DEL L001_IF: LDA _a$ LDS LDI 0 CMPEQ JPF L001_ELSE LDA _a$ LDS PRT JP L001_END L001_ELSE: LDA _c$ LDA _a$ LDS LDA _b$ LDS LDI 4 ADD MUL STS DEL LDA _c$ LDS PRT L001_END: STOP _END_PROG ----------------