命令セットの改良
#ComProc の2023/04/11時点の命令セット(旧ISA)から、新しいデータパスを利用した命令セット(新ISA)への進化 フレームポインタ管理
code:delay_ms.c
int delay_ms() {
int *t = 0;
*t = 2;
while (*t > 0) {}
return 0;
}
これを旧コンパイラでコンパイルすると、次のようなアセンブリコードになる
コメントは後から人間が書いた
code:delay_ms_old.as
delay_ms:
pushbp # ここから 4 行:FP = BP + 2
push 0x2
add
popfp
pushfp # ここから 4 行:FP += 2 ローカル変数 t のための領域を確保
push 0x2
add
popfp
push 0 # t の初期値の準備
pushbp # ここから 3 行:PUSH (BP + 2) t のアドレスをプッシュ
push 0x2
add
sta # 旧 ISA では stack0 にアドレス、stack1 にデータを置く pop
push 2
pushbp # ここから 3 行:PUSH (BP + 2)
push 0x2
add
ldd # t の値を読む
std # t が指す先へ 2 を書く
pop
L_0:
pushbp
push 0x2
add
ldd
ldd
push 0
lt
jz L_1
jmp L_0
L_1:
push 0
leave
ret
関数のローカル変数をスタックフレームに格納するために、フレームポインタ管理は必須
BPやFPの管理のためにかなり冗長な命令列となっている
L_0の手前までで22命令
新ISAで次のように書けるといいな
code:delay_ms_new.as
delay_ms:
cpush fp # FP をコールスタックに保存(delay_ms_old.as の先頭 5 行に相当)
addfp 2 # FP += 2 ローカル変数 t のための領域を確保
push 0 # t の初期値の準備
st cstack + 0 # t(cstack0 + 0)に stack0 の値を書く push 2 # 新 ISA でも stack0 にアドレス、stack1 にデータを置く ld cstack + 0 # t(cstack0 + 0)を読み stack にプッシュする std # t が指す先へ 2 を書く
pop
冗長性がかなり排除された
L_0の手前までで8命令