アセンブラでも関数型プログラミング
callで関数を実行し、returnで帰還
引数やローカル変数を使える
変数が関数内に隔離される
変数をグローバルで静的にメモリ配置する必要がない
mugyuuの投影に成功
https://gyazo.com/e18c413dae7a9b0520669d944dddd88a
code: main.m4
include(`init.m4')
title_str: "mugyuu";
main:
call(print, 1244, title_str);
goto(main);
print:
locals(vram_pointer', str_pointer');
arguments(position', str');
sread(position);
swrite(vram_pointer);
sread(str);
swrite(str_pointer);
print_char_loop:
sread(str_pointer);
inread;
write *autosp;
eq 0;
branch print_char_break;
read *autosp;
inread;
inwrite(sread(vram_pointer); );
sread(str_pointer);
add 1;
swrite(str_pointer);
sread(vram_pointer);
add 1;
swrite(vram_pointer);
goto(print_char_loop);
print_char_break:
read *autosp;
return;
code: init.m4
dnl m4マクロ定義
define(cat, $1$2$3$4$5$6$7$8$9)
dnl メモリマップ
define(`pc', 0)
define(`wreg', 1)
define(`sp', 2)
define(`autosp', 3)
define(`fractional', 4)
define(`inwrite_data', 128)
define(`inwrite_addr', 129)
dnl 拡張命令
define(goto', read $1; write pc')
define(mod', div $1; read *fractional')
define(nop', add 0')
define(`inread_label_count', 0)
dnl 間接読み込み
define(inread',
dnl 自己書き換えコード
write cat(`inread_label_', inread_label_count);
cat(`inread_label_', inread_label_count): 0;
define(`inread_label_count', eval(inread_label_count + 1))
')
dnl スタックからの相対読み込み
define(sread', read *sp; add $1; inread')
dnl 間接書き込み
define(inwrite',
write inwrite_data;
$1
write inwrite_addr;
read *inwrite_data;
write *inwrite_addr
')
dnl スタックからの相対書き込み
define(swrite', inwrite(read *sp; add $1; )')
define(`return_label_count', 0)
define(push_arguments',
ifelse(
$#, 0, ,
$#, 1, `read $1; write *autosp',
`push_arguments(shift($@)); read $1; write *autosp'
)
')
define(call',
push_arguments(shift($@), cat(`return_label_', return_label_count));
goto($1);
cat(`return_label_', return_label_count):
define(`return_label_count', eval(return_label_count + 1))
')
define(define_locals',
write *autosp;
ifelse(
$#, 0, ,
$#, 1, `
define($1, local_count);
define(`local_count', eval(local_count + 1))
',
`
define($1, local_count);
define(`local_count', eval(local_count + 1));
define_locals(shift($@))
'
)
')
define(locals',
define(`local_count', 0)
define_locals($@)
')
define(arguments',
ifelse(
$#, 0, ,
$#, 1, `
define($1, local_count);
define(`local_count', eval(local_count + 1))
',
`
define($1, local_count);
define(`local_count', eval(local_count + 1));
arguments(shift($@))
'
)
')
define(return',
read *sp;
add eval(local_count + 1);
write sp;
sread(-1);
write pc
')
dnl 電源投入時にCPUの安定を待ってプログラム開始
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
goto(main);