目次
前
次
中間言語方式検討
スクリプト言語でBASICインタプリタを作成すると
スクリプト言語を動かす環境が必要になります。
テキストのカタチで、プログラムを保存すると
マイコンのメモリを食潰していくので中間言語
を利用して、メモリ容量を有効利用すべきだと
多くの開発者が考えたことでしょう。
NECのPC8001、SHARPのMZ80B、FUJITSUのFM-8、FM-7
で採用されたBASICは、すべて中間言語に変換して
実行されていました。
中間言語を積極的に採用した言語はJavaでしょう。
バイトコードと呼ばれるプログラムを利用すると
バイトコードで記述されていれば、バイトコードを
実行する環境の用意するだけで、どのコンピュータ
でも同じプログラムが動くことになります。
開発したBASICインタプリタでも、テキストファイル
を中間言語に変換し、プログラムを実行できるように
したいと考えました。
ゼロから中間言語を定義するのは面倒なので
N88BASICで使われた中間言語を利用します。
N88BASICの中間言語は、1バイトと2バイトに分類されます。
1バイト中間言語
80hからFFhの128バイトで構成しています。
80 81 END
82 FOR 83 NEXT
84 DATA 85 INPUT
86 DIM 87 READ
88 LET 89 GO TO
8A RUN 8B IF
8C RESTORE 8D GOSUB
8E RETURN 8F REM
90 STOP 91 PRINT
92 CLEAR 93 LIST
94 NEW 95 ON
96 WAIT 97 DEF
98 POKE 99 CONT
9A OUT 9B LPRINT
9C LLIST 9D CONSOLE
9E WIDTH 9F ELSE
A0 TRON A1 TROFF
A2 SWAP A3 ERASE
A4 EDIT A5 ERROR
A6 RESUME A7 DELETE
A8 AUTO A9 RENUM
AA DEFSTR AB DEFINT
AC DEFSNG AD DEFDBL
AE LINE AF WHILE
B0 WEND B1 CALL
B2 B3
B4 B5 WRITE
B6 COMMON B7 CHAIN
B8 OPTION B9 RANDOMIZE
BA DSKO$ BB OPEN
BC FIELD BD GET
BE PUT BF SET
C0 CLOSE C1 LOAD
C2 MERGE C3 FILES
C4 NAME C5 KILL
C6 LSET C7 RSET
C8 SAVE C9 LFILES
CA MON CB COLOR
CC CIRCLE CD COPY
CE CLS CF PSET
D0 PRESET D1 PAINT
D2 TERM D3 SCREEN
D4 BLOAD D5 BSAVE
D6 LOCATE D7 BEEP
D8 ROLL D9 HELP
DA DB KANJI
DC TO DD THEN
DE TAB( DF STEP
E0 USR E1 FN
E2 SPC( E3 NOT
E4 ERL E5 ERR
E6 STRING$ E7 USING
E8 INSTR E9 '
EA VARPTR EB ATTR$
EC DSKI$ ED SRQ
EE OFF EF INKEY$
F0 > F1 =
F2 < F3 +
F4 - F5 *
F6 / F7 ^
F8 AND F9 OR
FA XOR FB EQV
FC IMP FD MOD
FE \ FF
2バイト中間言語
FF80hからFFFFhの128ワードで構成しています。
FF 80 FF 81 LEFT$
FF 82 RIGHT$ FF 83 MID$
FF 84 SGN FF 85 INT
FF 86 ABS FF 87 SQR
FF 88 RND FF 89 SIN
FF 8A LOG FF 8B EXP
FF 8C COS FF 8D TAN
FF 8E ATN FF 8F FRE
FF 90 INP FF 91 POS
FF 92 LEN FF 93 STR$
FF 94 VAL FF 95 ASC
FF 96 CHR$ FF 97 PEEK
FF 98 SPACE$ FF 99 OCT$
FF 9A HEX$ FF 9B LPOS
FF 9C CINT FF 9D CSNG
FF 9E CDBL FF 9F FIX
FF A0 CVI FF A1 CVS
FF A2 CVD FF A3 EOF
FF A4 LOC FF A5 LOF
FF A6 FPOS FF A7 MKI$
FF A8 MKS$ FF A9 MKD$
FF AA FF AB
FF AC FF AD
FF AE FF AF
FF B0 FF B1
FF B2 FF B3
FF B4 FF B5
FF B6 FF B7
FF B8 FF B9
FF BA FF BB
FF BC FF BD
FF BE FF BF
FF C0 FF C1
FF C2 FF C3
FF C4 FF C5
FF C6 FF C7
FF C8 FF C9
FF CA FF CB
FF CC FF CD
FF CE FF CF
FF D0 DSKF FF D1 VIEW
FF D2 WINDOW FF D3 POINT
FF D4 CSRLIN FF D5 MAP
FF D6 SEARCH FF D7 MOTOR
FF D8 PEN FF D9 DATE$
FF DA COM FF DB KEY
FF DC TIME$ FF DD WBYTE
FF DE RBYTE FF DF POLL
FF E0 ISET FF E1 IEEE
FF E2 IRESET FF E3 STATUS
FF E4 CMD FF E5
FF E6 FF E7
FF E8 FF E9
FF EA FF EB
FF EC FF ED
FF EE FF EF
FF F0 FF F1
FF F2 FF F3
FF F4 FF F5
FF F6 FF F7
FF F8 FF F9
FF FA FF FB
FF FC FF FD
FF FE FF FF
今回作成したBASICインタプリタでは、命令数が少ないので
すべて1バイトで表現することにします。
80 81 END
82 FOR 83 NEXT
84 85 INPUT
86 87
88 LET 89 GOTO
8A 8B IF
8C 8D GOSUB
8E RETURN 8F REM
90 91 PRINT
92 93
94 95
96 97
98 99
9A OUT 9B
9C 9D
9E 9F ELSE
A0 A1
A2 A3
A4 A5
A6 A7
A8 A9
AA AB
AC AD
AE AF WHILE
B0 WEND B1
B2 ENDIF B3
B4 B5
B6 B7
B8 B9
BA BB
BC BD
BE BF
C0 C1
C2 C3
C4 C5
C6 C7
C8 C9
CA CB
CC CD
CE CF
D0 D1
D2 D3
D4 D5
D6 D7
D8 D9
DA DB
DC TO DD THEN
DE DF STEP
E0 E1
E2 E3
E4 E5
E6 E7
E8 E9 '
EA EB
EC ED
EE EF
F0 > F1 =
F2 < F3 +
F4 - F5 *
F6 / F7 ^
F8 & F9 |
FA ? FB ,
FC FD
FE FF
1バイトでBASICのコードが表現できれば
中間言語に変換してメモリに格納するのと
中間言語のコードを実行するインタプリタ
を作成すれば、原理上は、どんなマイコン
でも同じプログラムが動くことになります。
AWKのスクリプトで、BASICプログラムを中間コードに
変換してみました。インデントした方が中間コード。
10 '
10 E9
12 LET <0>,100
12 88 <0> 100
13 LET C,3
13 88 43 33
14 LET <98>,89,90
14 88 <98> 89 90
15 LET A,10
15 88 41 10
17 LET B,20
17 88 42 20
20 LET <3>,10,20,A%3,B/3,<99>
20 88 <3> 10 20 A%3 B/3 <99>
30 Let A,A+10
30 88 41 A+10
35 Let a,a*3
35 88 41 A*3
40 print A
40 91 41
42 ? A,B,C,<0>,<3>,<4>,<5>,<6>,<7>
42 FA 41 42 43 <0> <3> <4> <5> <6> <7>
45 ? A,B+2
45 FA 41 B+2
50 GOTO 30
50 89 GOTO 30
60 IF A = 0 THEN LET <10>,<10>+1 ELSE LET <10>,<10>-1 ENDIF
60 8B 41 F1 0 0 DD 88 <10> <10>+1
65 IF A > 0 THEN LET <11>,<11>+1 ENDIF
65 8B 41 F0 0 0 DD 88 <11> <11>+1
70 WHILE B > 10
70 AF 42 F0 0 10
72 ? A
72 FA 41
74 ? B
74 FA 42
75 LET B,B-1
75 88 42 B-1
76 ? C
76 FA 43
78 WEND
78 B0
80 FOR I = 0 TO 4
80 82 49 F1 0 0 DC 4
82 ? A
82 FA 41
84 ? I
84 FA 49
86 NEXT
86 83
85 ? <10>,<11>
85 FA <10> <11>
90 END
90 81
スクリプトは、以下。
function isalpha(x) {
result = 0
# 'A' -> 'Z'
if ( "A" <= x && x <= "Z" ) { result = 1 }
# 'a' -> 'z'
if ( "a" <= x && x <= "z" ) { result = 1 }
return result
}
function get_hex(x) {
# convert capital letter
xtmp = toupper(x)
# default
result = xtmp
# reserved word
if ( xtmp == "IF" ) { result = "" }
if ( xtmp == "THEN" ) { result = "" }
if ( xtmp == "ENDIF" ) { result = "" }
if ( xtmp == "TO" ) { result = "" }
if ( xtmp == "END" ) { result = "" }
if ( xtmp == "FOR" ) { result = "" }
if ( xtmp == "NEXT" ) { result = "" }
if ( xtmp == "WHILE" ) { result = "" }
if ( xtmp == "WEND" ) { result = "" }
# judge
if ( length( xtmp ) == 1 ) {
if ( xtmp ~ /0/ ) { result = "30" }
if ( xtmp ~ /1/ ) { result = "31" }
if ( xtmp ~ /2/ ) { result = "32" }
if ( xtmp ~ /3/ ) { result = "33" }
if ( xtmp ~ /4/ ) { result = "34" }
if ( xtmp ~ /5/ ) { result = "35" }
if ( xtmp ~ /6/ ) { result = "36" }
if ( xtmp ~ /7/ ) { result = "37" }
if ( xtmp ~ /8/ ) { result = "38" }
if ( xtmp ~ /9/ ) { result = "39" }
if ( xtmp == "A" ) { result = "41" }
if ( xtmp == "B" ) { result = "42" }
if ( xtmp == "C" ) { result = "43" }
if ( xtmp == "D" ) { result = "44" }
if ( xtmp == "E" ) { result = "45" }
if ( xtmp == "F" ) { result = "46" }
if ( xtmp == "G" ) { result = "47" }
if ( xtmp == "H" ) { result = "48" }
if ( xtmp == "I" ) { result = "49" }
if ( xtmp == "J" ) { result = "4A" }
if ( xtmp == "K" ) { result = "4B" }
if ( xtmp == "L" ) { result = "4C" }
if ( xtmp == "M" ) { result = "4D" }
if ( xtmp == "N" ) { result = "4E" }
if ( xtmp == "O" ) { result = "4F" }
if ( xtmp == "P" ) { result = "50" }
if ( xtmp == "Q" ) { result = "51" }
if ( xtmp == "R" ) { result = "52" }
if ( xtmp == "S" ) { result = "53" }
if ( xtmp == "T" ) { result = "54" }
if ( xtmp == "U" ) { result = "55" }
if ( xtmp == "V" ) { result = "56" }
if ( xtmp == "W" ) { result = "57" }
if ( xtmp == "X" ) { result = "58" }
if ( xtmp == "Y" ) { result = "59" }
if ( xtmp == "Z" ) { result = "5A" }
}
return result
}
{
printf("%s\n",$0)
printf(" %s ",$1)
for ( i = 2 ; i <= NF ; i++ ) {
#
tmp = toupper($i)
# set flag
flag = 0
# REM
if ( tmp == "REM" ) { printf("8F ") }
#
if ( tmp == "END" ) { printf("81 ") }
# FOR
if ( tmp == "FOR" ) {
printf("82 ")
flag = 3
}
# NEXT
if ( tmp == "NEXT" ) { printf("83 ") }
# LET
if ( tmp == "LET" ) {
printf("88 ")
flag = 1
}
# GOTO
if ( tmp == "GOTO" ) { printf("89 ") }
# IF
if ( tmp == "IF" ) {
printf("8B ")
}
# GOSUB
if ( tmp == "GOSUB" ) { printf("8D ") }
# RETURN
if ( tmp == "RETURN" ) { printf("8E ") }
# REM
if ( tmp == "REM" ) { printf("8F ") }
# PRINT
if ( tmp == "PRINT" ) {
printf("91 ")
flag = 2
}
# OUT
if ( tmp == "OUT" ) { printf("9A ") }
# ELSE
if ( tmp == "ELSE" ) { printf("9F ") }
# WHILE
if ( tmp == "WHILE" ) { printf("AF ") }
# WEND
if ( tmp == "WEND" ) { printf("B0 ") }
# ENDIF
if ( tmp == "ENDIF" ) { printf("B2 ") }
# TO
if ( tmp == "TO" ) { printf("DC ") }
# THEN
if ( tmp == "THEN" ) { printf("DD ") }
# STEP
if ( tmp == "STEP" ) { printf("DF ") }
# '
if ( tmp == "\'" ) { printf("E9 ") }
# >
if ( tmp == ">" ) { printf("F0 ") }
# =
if ( tmp == "=" ) { printf("F1 ") }
# <
if ( tmp == "<" ) { printf("F2 ") }
# +
if ( tmp == "\+" ) { printf("F3 ") }
# -
if ( tmp == "\-" ) { printf("F4 ") }
# *
if ( tmp == "\*" ) { printf("F5 ") }
# /
if ( tmp == "\/" ) { printf("F6 ") }
# ^
if ( tmp == "^" ) { printf("F7 ") }
# &
if ( tmp == "&" ) { printf("F8 ") }
# |
if ( tmp == "\|" ) { printf("F9 ") }
# ?
if ( tmp == "\?" ) {
printf("FA ")
flag = 2
}
#
if ( flag == 1 || flag == 2 ) {
# get next field
j = i+1
# have commad
xx = $j
if ( index(xx,",") > 0 ) {
n = split($j,a,",")
for ( i = 1 ; i <= n+1 ; i++ ) {
printf("%s ",get_hex(a[i]))
}
} else {
ytmp = get_hex(xx)
printf("%s",ytmp)
}
break
}
#
if ( isalpha( tmp ) == 1 ) {
printf("%s ",get_hex( tmp ))
} else {
if ( tmp >= 0 ) { printf("%d ",tmp) }
}
}
printf("\n")
}
目次
前
次