差分

ナビゲーションに移動 検索に移動

インラインアセンブリ

2,671 バイト追加, 2013年9月5日 (木) 05:46
作成
'''インラインアセンブリ'''とは、[[C言語]]などの[[高級言語]]の[[コード]]中に[[アセンブリ言語]]のコードを書くテクニックである。

==主な利点==
* 元の高級言語では使えないテクニック([[キャリーフラグ]]や[[cpuid命令]]など)を使える
* [[高速化]]できることがある

==主な欠点==
* [[コンパイラ]]によって書き方が違うので、汎用性が低くなる
* [[ローカル]]環境では動いても[[オンラインジャッジ]]では[[ランタイムエラー]]になるなど、実行環境に依存した[[プログラム]]になることがある
* 慣れないと書きにくい

==使用例==
キャリーフラグを活用することにより、([[64ビット]]*64ビット) mod 64ビットの計算を[[オーバーフロー]]せずに行うコードを以下に示す。
<source lang="c">
/**
* (a*b)%cを計算する
* @param a 掛けられる数
* @param b 掛ける数
* @param c あまりを取る時に割る数
* @return (a*b)%cの計算結果
*/
unsigned long long repeat_add(
unsigned long long a,unsigned long long b,unsigned long long c) {
unsigned int a1,a2,b1,b2,c1,c2,r1,r2;
if(a>=c)a%=c;
a1=a>>32;a2=a;b1=b>>32;b2=b;c1=c>>32;c2=c;
__asm__ volatile (
"movl %6,%%ecx\n\t"
"movl %7,%%edx\n\t"
/* result=0; */
"movl $0,%0\n\t"
"movl $0,%1\n\t"
/* while(b>0) { */
"ra_while:\n\t"
"movl %4,%%eax\n\t"
"orl %5,%%eax\n\t"
"jz ra_exit\n\t"
/* if(b&1) { */
"movl %5,%%eax\n\t"
"andl $1,%%eax\n\t"
"jz ra_noif1\n\t"
/* result+=a; */
"movl %2,%%eax\n\t"
"movl %3,%%ebx\n\t"
"addl %%ebx,%1\n\t"
"adcl %%eax,%0\n\t"
/* if(result>=c) */
"jc ra_do_rmc\n\t"
"cmpl %%ecx,%0\n\t"
"ja ra_do_rmc\n\t"
"jb ra_noif1\n\t"
"cmpl %%edx,%1\n\t"
"jae ra_do_rmc\n\t"
"jmp ra_noif1\n\t"
/* result-=c; */
"ra_do_rmc:\n\t"
"sub %%edx,%1\n\t"
"sbb %%ecx,%0\n\t"
/* } */
"ra_noif1:\n\t"
/* a<<=1; */
"shll $1,%3\n\t"
"rcll $1,%2\n\t"
/* if(a>=c) */
"jc ra_do_amc\n\t"
"cmpl %%ecx,%2\n\t"
"ja ra_do_amc\n\t"
"jb ra_dont_amc\n\t"
"cmpl %%edx,%3\n\t"
"jae ra_do_amc\n\t"
"jmp ra_dont_amc\n\t"
/* a-=c; */
"ra_do_amc:\n\t"
"subl %%edx,%3\n\t"
"sbbl %%ecx,%2\n\t"
/* b>>=1; */
"ra_dont_amc:\n\t"
"shrl $1,%4\n\t"
"rcrl $1,%5\n\t"
/* } */
"jmp ra_while\n\t"
"ra_exit:\n\t"
: "=m"(r1),"=m"(r2)
: "m"(a1),"m"(a2),"m"(b1),"m"(b2),"m"(c1),"m"(c2)
: "%eax","%ebx","%ecx","%edx"
);
return (((long long)r1)<<32)|r2;
}
</source>

==関連項目==
* [[高級言語]]
* [[アセンブリ言語]]
* [[フラグ]]
匿名利用者

案内メニュー