シフト命令ってキャリーフラグ変化したよなーってことで、キャリーフラグを使ってみた。
インラインアセンブラの拡張構文勉強する羽目になりました。まあいいか。
インラインアセンブラ書くときに参考にしたサイトがここ。
インラインアセンブラで検索したら出てきたんだけど、ここのまん中ら辺、■19の項に、二進表示がまんま書いてあります。基本的にアプローチは同じなんですけど、みてみると良いかも。比較のためのCプログラムも出てるんですが、しっかりsizeof(int)とか使ってます。使わないとダメだよね。
インラインアセンブラの拡張構文勉強する羽目になりました。まあいいか。
インラインアセンブラ書くときに参考にしたサイトがここ。
インラインアセンブラで検索したら出てきたんだけど、ここのまん中ら辺、■19の項に、二進表示がまんま書いてあります。基本的にアプローチは同じなんですけど、みてみると良いかも。比較のためのCプログラムも出てるんですが、しっかりsizeof(int)とか使ってます。使わないとダメだよね。
#include <stdio.h> void dec2bin(unsigned int val, char *str) { int i; for( i = 0; i < 32; i++) { asm volatile ( " shll %0 \n" " jc _one \n" " movl $48, %2 \n" " jmp _asmend \n" "_one: \n" " movl $49, %2 \n" "_asmend:" :"=r" (val): "0" (val), "m" (str[i])); } str[32] = '\0'; } int main(int argc, char** argv) { int val; char str[33]; printf("Please input integer>"); scanf("%d", &val); dec2bin( (unsigned int)val, str); printf("%s\n", str); }
一応、アセンブラ部分の説明。
shll %0
変数%0を左に1ビットシフトします。最左bitが1ならCFフラグが立ちます。0ならCFが降ります。
jc _one
もし、CFフラグがたっていたら、ラベル_oneに飛びます。立ってなければすぐ下の命令を実行。
movl $48, %2
変数%2に48をセットします。48は'0'の文字コード。
jmp _asmend
無条件にラベル_asmendに飛びます。
_one: movl $49, %2
jcから飛んで来るところ。CFが立っていたら、変数%2に49をセットします。49は'1'の文字コード。
_asmend:
アセンブラ末尾のラベル。
:"=r" (val): "0" (val), "m" (str[i])
ここは良く理解していない。このコードによって、%0が変数valと、%2がstr[i]と対応づけられます。
以下は自分用メモ。
最初のコロンはアセンブリ文との区切り。
このコロンから次のコロンまでは、アセンブリコードの入力であることを表します。
rを指定しているので、入力として適当にレジスタが割り当てられます。
で、最初に出てきた変数がvalなので、アセンブリコードの中の%0はvalと対応づけられます。
次、もう一度コロンで区切られます。こっからさきは、出力変数になります。
valは、シフト命令で変更もされるので、出力変数でもあります。なので、ここでも宣言しないといけなくて、でも%0と対応しないといけないので、"0" (val)というふうに宣言してます。
それから、str[i]に文字0か1を出力するので、それも宣言します。"m"は、レジスタじゃなくて汎用メモリだよ、という意味です。三番目の宣言なので、str[i]は%2と対応づけられます。%1はvalと対応づけられてるのかな?よくわかりません。とにかく、str[i]は%1ではなく%2と対応づけられます。
要するに、アセンブリコードの中で中身を参照される変数は一個目のコロンと二個目のコロンの間で宣言しろってことで、アセンブリコードの中で中身を変更する変数は二個目のコロン以降で宣言しろってことかなぁと理解しました。
最初のコロンはアセンブリ文との区切り。
このコロンから次のコロンまでは、アセンブリコードの入力であることを表します。
rを指定しているので、入力として適当にレジスタが割り当てられます。
で、最初に出てきた変数がvalなので、アセンブリコードの中の%0はvalと対応づけられます。
次、もう一度コロンで区切られます。こっからさきは、出力変数になります。
valは、シフト命令で変更もされるので、出力変数でもあります。なので、ここでも宣言しないといけなくて、でも%0と対応しないといけないので、"0" (val)というふうに宣言してます。
それから、str[i]に文字0か1を出力するので、それも宣言します。"m"は、レジスタじゃなくて汎用メモリだよ、という意味です。三番目の宣言なので、str[i]は%2と対応づけられます。%1はvalと対応づけられてるのかな?よくわかりません。とにかく、str[i]は%1ではなく%2と対応づけられます。
要するに、アセンブリコードの中で中身を参照される変数は一個目のコロンと二個目のコロンの間で宣言しろってことで、アセンブリコードの中で中身を変更する変数は二個目のコロン以降で宣言しろってことかなぁと理解しました。