アセンブラでも関数型プログラミング

アセンブラでも関数型プログラミング

16命令アセンブラで、C言語のような関数型プログラミングをする
callで関数を実行し、returnで帰還
引数やローカル変数を使える
スタック領域から動的にメモリ確保、開放する
変数が関数内に隔離される
変数をグローバルで静的にメモリ配置する必要がない

mugyuu の投影に成功

main.m4
Copied!
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;


もはやm4マクロ定義のほうがコード長い
マクロアセンブラは、ボトムアップで独自言語を作れるのが面白いところ
init.m4
Copied!
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);

Powered by Helpfeel