2014/01/26
■ [z80][xlisp]自作Z80 CP/Mマシン(41)
引き続き XLISP ver1.1のメモ。
当初はif関数がうまく動かず、XLISP(と言うかLISP)をよく分らないし、Z80環境ではデバッグ環境が貧弱なので大変でした。 そこでいったん Linuxの GCCでコンパイル、解析してから CP/M側で修正し HI-TECH C Z80でコンパイルとデバッグしました。 なにせ GDBならソースコード単位での実行、ブレークや変数やリスト構造のポインタをたどって値を表示させたりできますので大変楽です。
そんな訳で x86_64(Linux)な GCCと Z80(CP/M) HI-TECH Cの両方でコンパイルしたので、出来上がった実行ファイルの大きさの比較をしてみました。(どちらも KEYMAPCLASSなし)
まずは GCC、 最適化なし(-O0)は 53,545バイト、 最適化あり(-Os)は 44,693バイトでした。
Z80 最適化なしは 39,310バイト、 最適化あり(-O)は 32,629バイトでした。 (DIRコマンドでは正確バイト数がわからないのでリンク時にマップファイルを出力させ、text+data+bssで計算しました。)
GCCは意外とバイナリが小さい印象です、 Z80はメモリ空間が64KBなので最適化して32Kバイトはやっぱ大きいです。
Z80の環境は CP/M 3.0、 HI-TECH C V3.09です、以下は最適化ありの時のマップファイル。
Machine type is Z80
0:J:CRTCPM.OBJ text 0 13D data 722A 1
XLISP.OBJ text 13D AF data 722B 13 bss 7BD0 8
XLREAD.OBJ text 1EC 738 data 723E AC bss 7BD8 4
XLEVAL.OBJ text 924 4BB data 72EA 8C bss 7BDC CE
XLPRIN.OBJ text DDF 30C data 7376 68 bss 7CAA 2
XLBIND.OBJ text 10EB 13A bss 7CAC 2
XLSUBR.OBJ text 1225 9BD data 73DE 100 bss 7CAE 2
XLLIST.OBJ text 1BE2 A15 data 74DE F2 bss 7CB0 12
XLMATH.OBJ text 25F7 780 data 75D0 36 bss 7CC2 2
XLOBJ.OBJ text 2D77 FF6 data 7606 1C1 bss 7CC4 10
XLFIO.OBJ text 3D6D 4CC data 77C7 69 bss 7CD4 65
XLIO.OBJ text 4239 14C data 7830 2A bss 7D39 A
XLSTR.OBJ text 4385 536 data 785A 2C
XLDMEM.OBJ text 48BB 6EF data 7886 110 bss 7D43 E
0:J:LIBC.LIB
printf.obj text 4FAA 1F
sprintf.obj text 4FC9 41 bss 7D51 8
doprnt.obj text 500A 2F3 data 7996 7 bss 7D59 5
gets.obj text 52FD BE
puts.obj text 53BB 55
fputc.obj text 5410 58
flsbuf.obj text 5468 A7
fopen.obj text 550F 4B
freopen.obj text 555A 135
fseek.obj text 568F 2C3
fread.obj text 5952 93
fgetc.obj text 59E5 84
filbuf.obj text 5A69 BB
stdclean.obj text 5B24 25 data 799D 40 bss 7D5E 200
fclose.obj text 5B49 67
fflush.obj text 5BB0 80
buf.obj text 5C30 46 bss 7F5E 2
exit.obj text 5C76 13
start1.obj text 5C89 3 bss 7F60 2
start2.obj text 5C8C 4E data 79DD 1
open.obj text 5CDA BE
read.obj text 5D98 268
write.obj text 6000 21C
seek.obj text 621C 181
creat.obj text 639D 7A
close.obj text 6417 79
unlink.obj text 6490 5F
getfcb.obj text 64EF 308 data 79DE 10
signal.obj text 67F7 73 bss 7F62 2
getuid.obj text 686A 26
bdos.obj text 6890 1E
bdoshl.obj text 68AE 16
cleanup.obj text 68C4 63 data 79EE 150
_exit.obj text 6927 B
asallsh.obj text 6932 12
allsh.obj text 6944 11
asladd.obj text 6955 9
atoi.obj text 695E 40
calloc.obj text 699E 66
asmul.obj text 6A04 F
ctype_.obj data 7B3E 81
strchr.obj text 6A13 15
iregset.obj text 6A28 26
ladd.obj text 6A4E E
longjmp.obj text 6A5C 53
brelop.obj text 6AAF 14
wrelop.obj text 6AC3 F
lrelop.obj text 6AD2 23
lsub.obj text 6AF5 10
malloc.obj text 6B05 315 bss 7F64 F
idiv.obj text 6E1A 68
pnum.obj text 6E82 15A data 7BBF 11
ldiv.obj text 6FDC 120
bmove.obj text 70FC 10
imul.obj text 710C 1F
alrsh.obj text 712B 14
sbrk.obj text 713F 43 bss 7F73 2
shll.obj text 7182 D
strcat.obj text 718F 1B
strcmp.obj text 71AA 1A
strcpy.obj text 71C4 12
strlen.obj text 71D6 E
csv.obj text 71E4 28
rcsv.obj text 720C 1E
TOTAL Name Link Load Length
(abs) 0 0 0
text 0 0 722A
data 722A 722A 9A6
bss 7BD0 7BD0 3A5
Symbol Table
__Hbss bss 7F75 __Hdata data 7BD0
__Htext text 722A __Lbss bss 7BD0
__Ldata data 722A __Ltext text 0000
__argc_ bss 7F60 __bufallo text 5C30
__buffree text 5C5A __cleanup text 5B24
__cpm_clean text 68C4 __ctype_ data 7B3E
__doprnt text 504B __exit text 6927
__fcb data 79EE __filbuf text 5A69
__flsbuf text 5468 __fsize text 621C
__getargs text 5C8C __iob data 799D
__pnum text 6E82 __putrno text 68E6
__sibuf bss 7D5E __sigchk text 682A
_anodes bss 7D45 _atoi text 6965
_bdos text 6890 _bdoshl text 68AE
_bmove text 70FC _brk text 713F
_calloc text 699E _cfree text 69F4
_checksp text 7173 _close text 6417
_creat text 639D _exit text 5C76
_fc_parse text 65F0 _fclose text 5B49
_fexit text 1A91 _fflush text 5BB0
_fgetc text 59E5 _fgets text 52FD
_fopen text 550F _fputc text 5410
_fputs text 53BB _fread text 5952
_free text 6CDE _freopen text 555A
_fseek text 577E _ftell text 58D1
_gccalls bss 7D4F _getfcb text 650E
_gets text 5375 _getuid text 686A
_longjmp text 6A89 _lseek text 62EB
_main text 013D _malloc text 6B05
_movmem text 70FC _newnode text 48BB
_nfree bss 7D43 _nnodes bss 7D49
_nsegs bss 7D4B _oblist bss 7BD8
_open text 5CDA _printf text 4FAA
_putfcb text 654D _puts text 53F0
_read text 5D98 _realloc text 6CF8
_sbrk text 7147 _self bss 7CCA
_setfcb text 6560 _setjmp text 6A5C
_setuid text 687E _signal text 67F7
_sprintf text 4FC9 _stralloc text 491A
_strcat text 718F _strchr text 6A13
_strcmp text 71AA _strcpy text 71C4
_strfree text 4992 _strlen text 71D6
_strsave text 495E _unlink text 6490
_write text 6000 _xlabind text 0C08
_xladdivar text 31B2 _xladdmsg text 363B
_xlarg text 12AE _xlbind text 1137
_xlclass text 2D77 _xlcvar text 3B1F
_xldmeminit text 4F63 _xleinit text 0DC1
_xlenter text 0596 _xlenv bss 7CAC
_xleval text 097D _xlevarg text 136A
_xlevmatch text 13B2 _xlfail text 0D1C
_xlfin text 430C _xlfinit text 41EF
_xlfixbindings text 1194 _xlgetc bss 7D3D
_xlinit text 1B49 _xlivar text 3ABC
_xljmpbuf bss 7BD0 _xllastarg text 141F
_xllinit text 24CF _xlmatch text 12FD
_xlmfind text 2E54 _xlminit text 2C6D
_xlobsym text 3040 _xloinit text 3BFC
_xlpinit text 10C7 _xlplevel bss 7D3B
_xlprint text 0E69 _xlpvals bss 7D41
_xlread text 01EC _xlsave text 09D5
_xlsend text 2FEF _xlsinit text 4865
_xlstack bss 7CA8 _xlsubr text 1225
_xlsvar text 1261 _xltin text 4293
_xlunbind text 10EB _xlxsend text 2E72
_xprint text 0E07 _xprogn text 1AEB
adiv text 6E29 aladd text 6A4E
aldiv text 7028 allsh text 6944
almod text 704F alrsh text 712B
alsub text 6AF5 amod text 6E1A
amul text 710C arelop text 6AD2
asaladd text 6955 asaldiv text 7013
asallsh text 6932 asalmod text 7061
asamul text 6A04 aslladd text 6955
aslldiv text 7047 aslllsh text 6932
asllmod text 7074 aslmul text 6A04
brelop text 6AAF cret text 71F0
csv text 71E4 indir text 71F7
iregset text 6A28 iregstore text 6A42
ldiv text 6E24 lladd text 6A4E
lldiv text 703B lllsh text 6944
llmod text 7069 llsub text 6AF5
lmod text 6E1F lmul text 710C
lrelop text 6AD2 ncsv text 71F8
rcsv text 720C shal text 7182
shll text 7182 start text 0100
startup text 5C89 wrelop text 6AC3
2014/01/23
■ [z80][xlisp]自作Z80 CP/Mマシン(40)
引き続き XLISP ver1.1のメモ。
if関数もちゃんと動くようになったので簡単なプログラムを書いてみました。
P>TYPE TEST.LSP
; TEST.LSP
;
; 関数 nib 0〜15を"0"〜"F"に変換
;
(defun nib (n)
(chr (+ n (if (< n 10) 48 55))))
;
; 関数 byte 0〜255を"00"〜"FF"に変換
;
(defun byte (n)
(strcat (nib (& 15 (/ n 16)))
(nib (& 15 n))))
;
; 0〜255 まで16進で表示、16ごとに改行する
;
(setq i 0)
(while (< i 256)
(princ (byte i)
(if (== (% i 16) 15) "\n" " "))
(setq i (+ i 1)))
P>XLISP TEST.LSP <-- 実行する
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 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 DD DE DF
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
P>
ファイルの内容を表示する(例では"MAKEFILE")
P>TYPE TEST2.LSP
;
; TEST2.LSP ファイルの内容を表示
;
(setq f (fopen "MAKEFILE" "r"))
(while (setq c (getc f))
(princ (chr c))
)
(fclose f)
(exit)
P>XLISP TEST2.LSP <-- 実行する
CC = j:c
CFLAGS = -O
# CFLAGS = -g -O0
objs = xlisp.obj xlread.obj xleval.obj xlprin.obj xlbind.obj \
xlsubr.obj xllist.obj xlmath.obj xlobj.obj \
xlfio.obj xlio.obj xlstr.obj xldmem.obj
xlisp: $(objs)
$(objs): xlisp.h
.c.obj:
$(CC) $(CFLAGS) -c $<
clean:
era xl*.obj
era xlisp.com
era link.map
P>
ファイルを16進ダンプする(例では"MAKEFILE")
P>TYPE TEST3.LSP
;
; TEST3.LSP - ファイルを16進ダンプする
;
(defun nib (n)
(chr (+ n (if (< n 10) 48 55))))
(defun byte (n)
(strcat (nib (& 15 (/ n 16))) (nib (& 15 n))))
(setq i 0)
(setq f (fopen "MAKEFILE" "rb"))
(while (setq c (getc f))
(princ (byte c)
(if (== (% i 16) 15) "\n" " "))
(setq i (+ i 1)))
(fclose f)
(exit)
P>XLISP TEST3.LSP <-- 実行する
43 43 09 3D 20 6A 3A 63 0D 0A 43 46 4C 41 47 53
20 3D 20 2D 4F 0D 0A 23 20 43 46 4C 41 47 53 20
3D 20 2D 67 20 2D 4F 30 0D 0A 0D 0A 6F 62 6A 73
20 3D 20 09 78 6C 69 73 70 2E 6F 62 6A 20 78 6C
72 65 61 64 2E 6F 62 6A 20 78 6C 65 76 61 6C 2E
6F 62 6A 20 78 6C 70 72 69 6E 2E 6F 62 6A 20 78
6C 62 69 6E 64 2E 6F 62 6A 20 5C 0D 0A 09 78 6C
73 75 62 72 2E 6F 62 6A 20 78 6C 6C 69 73 74 2E
6F 62 6A 20 78 6C 6D 61 74 68 2E 6F 62 6A 20 78
6C 6F 62 6A 2E 6F 62 6A 20 5C 0D 0A 09 78 6C 66
69 6F 2E 6F 62 6A 20 78 6C 69 6F 2E 6F 62 6A 20
78 6C 73 74 72 2E 6F 62 6A 20 78 6C 64 6D 65 6D
2E 6F 62 6A 0D 0A 0D 0A 78 6C 69 73 70 3A 20 24
28 6F 62 6A 73 29 0D 0A 0D 0A 24 28 6F 62 6A 73
29 3A 20 78 6C 69 73 70 2E 68 0D 0A 0D 0A 2E 63
2E 6F 62 6A 3A 0D 0A 09 24 28 43 43 29 20 24 28
43 46 4C 41 47 53 29 20 2D 63 20 24 3C 0D 0A 0D
0A 63 6C 65 61 6E 3A 0D 0A 09 65 72 61 20 78 6C
2A 2E 6F 62 6A 0D 0A 09 65 72 61 20 78 6C 69 73
70 2E 63 6F 6D 0D 0A 09 65 72 61 20 6C 69 6E 6B
2E 6D 61 70 0D 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
P>
(環境は CP/M Z80 HI-TECH C ver3.09でコンパイル)
2014/01/19
■ [z80][xlisp]自作Z80 CP/Mマシン(39)
引き続き XLISPのメモ。
うまく動かない if関数を調べるために確認用の printfを追加して流れを追ったり、デバッガをかけて引数をチェックしたりとしてみましたが、どうやらソース自体が間違っていそうなので後のバージョンのソースを探して比べて見ました。
下に ver1.1と 1.2の該当部分のソースを示しますが、やはり処理が違っています、修正されたのでしょうねぇ、、
具体的には、 引数の取り出しが xlmatch(LIST, &arg.n_ptr) から xlarg(&args) へ、 引数の評価が xlevarg(thenexpr.n_ptr) から xleval(thenexpr.n_ptr) へ変わっています。
XLISP v1.1 xlsubr.c
/* fif - builtin function if */
static struct node *fif(args)
struct node *args;
{
struct node *oldstk,arg,testexpr,thenexpr,elseexpr,*val;
int dothen;
/* create a new stack frame */
oldstk = xlsave(&arg,&testexpr,&thenexpr,&elseexpr,NULL);
/* initialize */
arg.n_ptr = args;
/* evaluate the test expression */
testexpr.n_ptr = xlevarg(&arg.n_ptr);
/* get the then clause */
thenexpr.n_ptr = xlmatch(LIST,&arg.n_ptr); <- 真の場合の引数を取り出し
/* get the else clause */
if (arg.n_ptr != NULL)
elseexpr.n_ptr = xlmatch(LIST,&arg.n_ptr); <- 偽の場合の引数を取り出し
else
elseexpr.n_ptr = NULL;
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* figure out which expression to evaluate */
dothen = testvalue(testexpr.n_ptr);
/* default the result value to the value of the test expression */
val = testexpr.n_ptr;
/* evaluate the appropriate clause */
if (dothen)
while (thenexpr.n_ptr != NULL)
val = xlevarg(&thenexpr.n_ptr); <- 真の評価
else
while (elseexpr.n_ptr != NULL)
val = xlevarg(&elseexpr.n_ptr); <- 偽の評価
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last value */
return (val);
}
XLISP v1.2 xlcont.c
/* xif - builtin function 'if' */
struct node *xif(args)
struct node *args;
{
struct node *oldstk,testexpr,thenexpr,elseexpr,*val;
/* create a new stack frame */
oldstk = xlsave(&testexpr,&thenexpr,&elseexpr,NULL);
/* get the test expression, then clause and else clause */
testexpr.n_ptr = xlarg(&args); <- 真の場合の引数を取り出し
thenexpr.n_ptr = xlarg(&args); <- 偽の場合の引数を取り出し
elseexpr.n_ptr = (args ? xlarg(&args) : NULL);
xllastarg(args);
/* evaluate the appropriate clause */ <- 真・偽の評価
val = xleval(xleval(testexpr.n_ptr) ? thenexpr.n_ptr : elseexpr.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last value */
return (val);
}
修正後は思ったとおりの結果になりました。
P>xlisp XLISP version 1.1 > (if t 1 2) 1 <- 1 が返ってくる > (if t (1)(2)) error: bad function <- エラーになる (1) (if t (1) (2))
(環境は CP/M Z80 HI-TECH C ver3.09でコンパイル)