0

ほとんどの命令セットでは、ステータス レジスタのフラグに基づいて分岐命令が実行されます。

高水準言語では、ブール値は評価式 (一般に ==、!=、<、>、>=、<= およびその他のバリアント) によって作成され、変数に格納できるデータ型です。

ブール値の結果をレジスタに格納する命令を使用する代わりに、アセンブリがステータスフラグで分岐することを選択するのはなぜですか?

テストの結果を変数に格納できる言語の数を考えると、命令セットもそれに合わせて進化し、より効率的なプログラムを作成できる可能性があると考えていました。

テスト結果をステータス レジスタに格納してからフラグで分岐するというこの規則は単なる伝統なのでしょうか、それとも汎用レジスタから直接格納してテストするよりもフラグ ベースの方法の方が効率的であると示唆する理由はありますか?

4

3 に答える 3

3

「ブール値の結果をレジスタに格納する」場合は<<=>>=、 などの個別の命令が必要になります。また、符号付き比較用に 1 セット、符号なし比較用に別のセットが必要です。

x86 命令セットでは、これらすべてに対して 1 つの命令がありcmp(多数のフラグを設定します)、適切なor命令を使用して、関心のあるフラグを調べます (たとえば、条件付きジャンプの場合は、/ , , /符号なし (「下」/「上」) の場合、および/ , , /符号付き( 「少ない」/「大きい」) の場合)。jxxsetxxjbjbejnajajaejnbjljlejngjgjgejnl

このアプローチのもう 1 つの特徴は、足し算や引き算の借用など、ミューテーション操作を行った後に実際にフラグをチェックできることです。esi例 ( が指している別の 128 ビット量に追加されている 128 ビット数を指していると仮定しますedi):

add [edi], [esi]
adc [edi+4], [esi+4]
adc [edi+8], [esi+8]
adc [edi+12], [esi+12]
jc overflow

これはたったの 5 命令です (まあ、仮説ですが、実際には、x86 命令では両方のオペランドをアドレスにすることはできず、1 つをレジスタにする必要があります。つまり、そのレジスタをロードするには、より多くの命令が必要になります)。「レジスタ内のブール値の結果」アプローチを使用すると、より複雑になるように思えます (ただし、3 通りの加算を許可する命令セットを使用している場合は、それほど多くはないと思います)。

于 2013-09-06T00:27:09.850 に答える
1

クリスの答えは正しいです。比較の結果を保持するためだけに大きなレジスタを拘束したくないことに加えて、フラグビットは算術レジスタ操作から自然に外れ、特別に指定されたフラグレジスタはそれらに適した場所であることを付け加えるだけです。

2 つのレジスタ間で加算が実行されるたびに、桁上げビットにオーバーフローが発生する可能性があり、減算は加算の一種です。

数値が 2 の補数の場合、レジスタの上位ビットは符号ビットです。

また、すべての加算/減算の後、いくつかの特別なハードウェアが結果がすべてゼロであるかどうかを検出します。これは、フラグに追加する別のビットです。

すべての算術比較は、これらの組み合わせに要約されるため、条件分岐や長整数演算などに簡単に使用できます。

基本レベルのハードウェアの私のお気に入りの例は、Harry Porters の Relay Computerです。そこには、フラグ レジスタがハードウェアを最小限に抑え、命令セットを簡素化するのに実際にどのように役立つかがわかります。

于 2013-09-06T00:49:21.800 に答える