2010-12-27 16 views
5

GNUプロジェクトの一部のソースコードを読みながら、私はインラインアセンブリのこのビットに出くわした:ここヘルプ理解DIV命令は

__asm__ (
    "divq %4" 
    : "=a" (q), "=d" (r) 
    : "0" (n0), "1" (n1), "rm" (d) 
); 

変数qrn0n1、そしてdは64ビット整数です。私は、これがしていることの要点を得るのに十分なアセンブリを知っていますが、私が確信していない詳細がいくつかあります。私が理解

我々は、dによってRAXレジスタの内容を分割qで商を配置し、rで残りを置いています。私はなぜ入力が ここにあります

  1. を理解していない何

    ? の配当と除数を入力するだけでよいので、3入力の場合は を使用することができますか?

  2. 入力のどれが配当であるかわかりません。より一般的には、実際には何も表示されません RAXレジスタにロードされています、 どのように分けて何を分かっていますか?
+1

+1形式の質問です。私は "私が理解するもの"と "私が理解できないもの"のセクションが好きです。 –

答えて

4

: "0" (n0), "1" (n1), "rm" (d) 

レジスタは "0" と "1" があるため、出力仕様のraxrdxを余儀なくされています

: "=a" (q), "=d" (r) 

や家族が望んでいるdiv命令分子はRDX:RAXです。除数は、汎用レジスタ(別途使用されていない - すなわち、RAXまたはRDXではない)または "rm"制約で指定されたメモリに入れることができます。レジスタRDX,RAX、および除数オペランドが3つの入力を構成します。

これで分割が行われます。n1:n0/dここで、n1:n0は、rdx:raxに読み込まれた数です。

+0

これは128ビット整数を64ビット整数で除算するために使用できることを正しく理解していますか?私はこれが32ビットレジスタバージョンで可能であることは知っていましたが、64ビットバージョンでもこれを保持するとは考えていませんでした。 –

+1

@Jens:そうです。しかし、(小さいオペランドの除算演算のように)商が 'rax'デスティネーションレジスタのために大きすぎる場合、除算例外が発生することに注意してください。 –

+1

このケースをテストする簡単な方法は、 'rdx'が除数より小さいことを確認することです。この場合、除算は安全です。 –

0

あなたは正しくdiv家族が固定レジスタadraxdivqためrdxで動作を観察したよう。 aレジスタはn0から入力を受け取ります。n0は0番目のレジスタにエイリアスされています。つまり、aです。 n1は、dにエイリアスされたダミー入力です。おそらく、このレジスタが他の目的に使用されないようにするためです。入力オペランドの指定で