拡張インラインアセンブラの勉強 1
06 April 2012
拡張インラインアセンブラ、けっこう難しくてなかなか覚えられません。。
GCC Inline Assembler というサイトを見ながら、もう一回勉強してみた。
基本的に
asm( アセンブリテンプレート : 出力オペランド : 入力オペランド : 破壊レジスタ);
というフォーマットでいいのですが、「出力オペランド」と「入力オペランド」はわかるとして、 「破壊レジスタ」というのがいまいちピンときません。
そこで、「破壊レジスタ」を指定するのとしないのとで、どのような違いが出るのか、 ARM gcc の逆アセを見ながら勉強してみた。
まずは、普通に(拡張でない)インラインアセンブラを書いた場合
int hoge()
{
register int a = 10, b = 20;
asm("mov r4, #100");
return a + b;
}
をコンパイルすると
<hoge>:
push {r4, r5, fp}
add fp, sp, #8
mov r5, #10
mov r4, #20
mov r4, #100 ; 0x64
add r3, r5, r4
mov r0, r3
sub sp, fp, #8
pop {r4, r5, fp}
bx lr
となった。
コンパイラは前後関係を考慮することなく、単に mov r4, #100
を挿入するだけなので、
30
ではなく、 110
を返すコードが生成された。
(変数 b
が r4
に取られているためだが、これは事前に予測不能である。)
そこで拡張インラインアセンブラを使って、 r4
が破壊されることを指定する。
int hoge()
{
register int a = 10, b = 20;
asm("mov r4, #100" : : : "r4");
return a + b;
}
は
<hoge>:
push {r4, r5, r6, fp}
add fp, sp, #12
mov r6, #10
mov r5, #20
mov r4, #100 ; 0x64
add r3, r6, r5
mov r0, r3
sub sp, fp, #12
pop {r4, r5, r6, fp}
bx lr
なるほど、 r4
を避けて、 変数 a
, b
を r6
, r5
に割り当てています。
しかもちゃんと r4
をスタックに退避してくれています。
ではコンパイラを困らせてやれと思って、
int hoge()
{
register int a = 10, b = 20;
asm("mov r4, #100" : : : "r4", "r5", "r6", "r7", "r8", "r9", "r10");
return a + b;
}
とすると、
<hoge>:
push {r4, r5, r6, r7, r8, r9, sl, fp}
add fp, sp, #28
sub sp, sp, #8
mov r1, #10
str r1, [fp, #-32] ; 0xffffffe0
mov r2, #20
str r2, [fp, #-36] ; 0xffffffdc
mov r4, #100 ; 0x64
ldr r1, [fp, #-32] ; 0xffffffe0
ldr r2, [fp, #-36] ; 0xffffffdc
add r3, r1, r2
mov r0, r3
sub sp, fp, #28
pop {r4, r5, r6, r7, r8, r9, sl, fp}
bx lr
となった。
レジスタ変数をとれなくなって、変数 a
, b
はスタックに確保している。
ただし、破壊レジスタに r11
を指定すると
error: fp cannot be used in asm here
というエラーが出る。
一応、以下のようにほとんど破壊レジスタリストに指定しても、つじつまの合うように動くようです。
int hoge()
{
register int a = 10, b = 20;
asm("mov r13, #0x81000000" : : :
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r12", "r13", "r14");
return piyo(a, b);
}
をコンパイルすると、
<hoge>:
push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
add fp, sp, #32
sub sp, sp, #12
mov r3, #10
str r3, [fp, #-40] ; 0xffffffd8
mov r3, #20
str r3, [fp, #-44] ; 0xffffffd4
mov sp, #-2130706432 ; 0x81000000
ldr r0, [fp, #-40] ; 0xffffffd8
ldr r1, [fp, #-44] ; 0xffffffd4
bl <piyo>
mov r3, r0
mov r0, r3
sub sp, fp, #32
pop {r4, r5, r6, r7, r8, r9, sl, fp, pc}
blog comments powered by Disqus