acl4のプログラムのページ0005

  • (by K, 2026.02.16)

(1) 実行したい

  • a4_p0004でソースコードをバイナリにするのが簡単だとわかったので、インタプリタ実行をしてみることにしました。

(2) p0005a.c [59行] : 即興で作った仮想マシン

#define a_Version 1
#include <acl4.c>

void myPut(Preprocessor_Put0 *w, VecChr *lin) // t0013b.cで作ったやつと同じ.
{
    if (Preprocessor_isDirective(lin->p, lin->p + lin->n) != 0)
        fprintf(stderr, "[err] %.*s", (int) lin->n, lin->p);
    else
        VecChr_puts(w->dst, lin->p, lin->p + lin->n);
}

int main(int argc, const char **argv)
{
    if (argc < 2) return 1;
    Preprocessor pp[1]; Preprocessor_ini(pp);                            // プリプロセッサの初期化.
    pp->put = (void *) myPut;                                            // 出力関数の変更.
    Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 入力ファイルを指定.
    Preprocessor_SourceFiles_addFile(pp->sfs, "a4vm-asm-p0005a.h", 17);  // 最初にこれをインクロードさせる.
    VecChr vc[1]; VecChr_ini(vc); pp->put0->dst = vc;                    // 出力先のオブジェクトを指定.
    Preprocessor_main(pp); Preprocessor_din(pp);                         // プリプロセッサ処理. およびメモリ開放.

    Token0 t0[1]; Token0_ini1(t0);
    t0->s = vc->p; t0->s1 = vc->p + vc->n;
    Preprocessor_Eval ev[1]; ev->err = 0;
    VecChr bin[1]; VecChr_ini(bin);
    for (;;) {
        intptr_t i = Preprocessor_eval(ev, t0, 0x7fff);
        if (ev->err != 0) break;
        VecChr_resizeDiff(_arg_  bin, 1); bin->p[bin->n - 1] = (char) i;
        Token1_get(t0);
        if (t0->c != ',') break;
    }

    int32_t *bp = (int32_t *) bin->p, bn = bin->n / sizeof (int32_t), reg[256], lab[256], pc;
    for (pc = 0; pc < bn; pc += 4) {
        if (bp[pc] == 0x02)
            lab[bp[pc + 1]] = pc + 4;  // Lbl_T(t)命令の次の命令を指す.
	 }
	 for (pc = 0;;) {
            int32_t op = bp[pc], a = bp[pc + 1], b = bp[pc + 2], c = bp[pc + 3]; pc += 4;
            switch (op) {
            case 0x01: reg[a] = b;                       continue; // Lod_RI(r,i)
            case 0x02:                                   continue; // Lbl_T(t)
            case 0x03: reg[a] += reg[b];                 continue; // Add_RR(r,s)
            case 0x04: reg[a] += b;                      continue; // Add_RI(r,i)
            case 0x05: if (reg[a] <= b) { pc = lab[c]; } continue; // Jle_RIT(r,i,t)
            case 0x06: if (reg[a] <  b) { pc = lab[c]; } continue; // Jlt_RIT(r,i,t)
            case 0x10: goto fin;
            case 0x11: goto fin;
            case 0x12: putchar(reg[a]);                  continue; // Dbg_Putc_R(r)
            case 0x13: putchar(a);                       continue; // Dbg_Putc_I(i)
            case 0x16: printf("%d", reg[a]);             continue; // Dbg_PutDec_R(r)
        }
    }
fin:
    VecChr_din4(vc, bin, 0, 0);
    a_malloc_debugList(_arg);
    return 0;
}
  • 適当に作った定義ファイル: a4vm-asm-p0005a.h (内容は仮です。たぶん全部作り直します。)
    #define R00  0
    #define R01  1
    #define R02  2
    #define R03  3
    #define L0000    0
    #define L0001    1
    #define L0002    2
    #define L0003    3
    
    #define _i8(i)    (i)&0xff
    #define _i16(i)   _i8(i),_i8((i)>>8)
    #define _i32(i)   _i16(i),_i16((i)>>16)
    #define _op(i)    _i32(i)
    #define _op128(i0,i1,i2,i3)  _i32(i0),_i32(i1),_i32(i2),_i32(i3)
    
    #define Lod_RI(r,i)      _op128(0x01,r,i,0),
    #define Lbl_T(t)         _op128(0x02,t,0,0),
    #define Add_RR(r,s)      _op128(0x03,r,s,0),
    #define Add_RI(r,i)      _op128(0x04,r,i,0),
    #define Jle_RIT(r,i,t)   _op128(0x05,r,i,t),
    #define Jlt_RIT(r,i,t)   _op128(0x06,r,i,t),
    #define Dbg_Ret_R(r)     _op128(0x10,r,0,0),
    #define Dbg_Ret_I(i)     _op128(0x11,i,0,0),
    #define Dbg_Putc_R(r)    _op128(0x12,r,0,0),
    #define Dbg_Putc_I(i)    _op128(0x13,i,0,0),
    #define Dbg_PutHex_R(r)  _op128(0x14,r,0,0),
    #define Dbg_PutHex_I(i)  _op128(0x15,i,0,0),
    #define Dbg_PutDec_R(r)  _op128(0x16,r,0,0),
    #define Dbg_PutDec_I(i)  _op128(0x17,i,0,0),

(3) 実行結果

  • p0004a0.txt:
    #define c   R00 // 整数レジスタ
    #define lp  L0000 // ラベル
    
      Lod_RI(c, 0x20)
    Lbl_T(lp)
      Dbg_Putc_R(c)
      Add_RI(c, 1)
      Jlt_RIT(c, 0x7f, lp)
      Dbg_Putc_I('\n')
      Dbg_Ret_I(0)
>p0005a p0004a0.txt
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
  • こんな感じでちゃんと動いています。
  • p0005a0.txt:
    #define i   R00 // 整数レジスタ
    #define s   R01
    #define lp  L0000 // ラベル
    
      Lod_RI(s, 0)
      Lod_RI(i, 0)
    Lbl_T(lp)
      Add_RR(s, i)
      Add_RI(i, 1)
      Jle_RIT(i, 1000, lp)
      Dbg_PutDec_R(s)
      Dbg_Putc_I('\n')
      Dbg_Ret_I(0)
>p0005a p0005a0.txt
500500
  • これも問題なく動きました。

(99) 更新履歴

  • 2026.02.16(月) 初版

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2026-02-16 (月) 11:23:36 (120d)