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でコンパイル)