2016-11-09 11 views
3

最近、私はAssembly言語に遭遇しました。アセンブリには、2つのレジスタの内容を交換するxchg指令があります。すべてのCコードが最初にAssemblyに変換されるので、ヘッダstdio.hのようにCにスワップ関数inbuiltがあったといいでしょう。コンパイラがスワップ機能を検出するたびに、アセンブリファイルにxchg命令を追加することができます。 なぜこのスワップ関数がCで実装されていないのですか?Cで組み込みのスワップ関数がないのにAssemblyにxchgがあるのはなぜですか?

+2

Cが開発されたとき、これは一般的な指示ではなかったかもしれないので、彼らはその点を見ませんでした。 – Barmar

+6

"アセンブリにはxchgディレクティブがあります" *どの* assember? *プラットフォームは何ですか? –

+4

Cでは多くの機械語で回転機能はありません。そしてどの「アセンブリ」を参照していますか?多くのCPUはそのような命令を持っていません。 – Olaf

答えて

6

は、クロスプラットフォーム言語です。アセンブリはアーキテクチャ固有のものです。すべてのアーキテクチャがそのような命令を持っているわけではありませんさらに、Cは、機械語の命令セットと機能に対応する必要はなく、 "人間"言語と機械語の間を橋渡しして模倣するのではなく、この具体的なアーキテクチャのCコンパイラは、このスワップ命令の拡張子を持っているか、スマートなら十分にこの命令を使うようスワッピングコードを最適化します。

+1

言語機能は、すべてのアーキテクチャにある指示に対応する必要はありません。浮動小数点ハードウェアを持たないアーキテクチャにCを実装することができます。代わりにソフトウェアでCを実装します。 – Barmar

+0

興味深い質問が残っています。なぜ、Cコンパイラによってx86以外のアーキテクチャでエミュレートされないのですか? – zx485

+0

@ zx485あなたはそれが言語の一部として追加するのに十分役に立つと思いますか?私はしない... –

4

これは、レジスタに収まり、レジスタ内にある変数に対して機能します。大きな構造体や変数がメモリに格納されている場合は機能しません(reg Xに変数Aをロードし、reg YにBを入れてスワップすると、スワッピングをスキップしてAのYとBのXを直接ロードできます)。これらは、レジスタであることを起こる場合...

int a; 
int b; 
int tmp; 
tmp=a; 
a=b; 
b=tmp; 

を::

言っては何もスワップ命令を使用するために与えられたアーキテクチャのためのコンパイラがコンパイルに防ぐない、と述べたそれはCではないという事実コンパイラがそれを使用しないことを意味しません。

0

xchgは非常に基本的な命令ですが、これはCに相当するものが必要であるということを意味しません。 C が時々がアセンブリに直接マップされているという事実はあまり関係ありません。標準では「アセンブリ」について何も言及していません(アセンブリにマップする理由と、別の低レベル言語ではないのはなぜですか?)。

質問するかもしれません:Cに組み込みのベクトル命令がないのはなぜですか?彼らは主に利用可能になっています!

コンパイラの助けもあります:変数を入れ替えるのは非常に目に見えるパターンなので、このような最適化を実装するのは難しくありません。また、インラインでasmが必要です。

2

swap()はC

ではない理由

1.関数呼び出しの意味を説明できる2つのポイントがあります。
swap()機能を含むが、Cで非常に基本的な設計上の決定を破る:swap()だけで動作することができますが、参照渡しのセマンティクス(C++は言語に追加されていますが、C言語では存在しません)であり、値渡しではありません。可能なアセンブラ命令とは別に

2.多様性は、通常、割り込み処理命令などの多様なこれは命令を含み、純粋なCから完全にアクセスできません任意のCPUアーキテクチャ上のアセンブラ命令のかなりの数があり、仮想メモリ空​​間操作命令、I/O命令、ビット・バイディング命令(GoogleのPPC命令rlwimi、これは特に強力な例です)など

任意のOSは非常に少なくともいくつかの小さなに含まなければならない理由である、これらのいくつかは、オペレーティングシステムを実装するために重要であるC.

のような汎用的な言語では、これらの任意のかなりの数が含まれるように、単純に不可能ですアセンブラコードの量これらは、通常、インラインアセンブラを使用していくつかの関数にカプセル化されているか、プリプロセッサディレクティブとしてカーネルヘッダに定義されています。他の命令はそれほど重要ではなく、最適化にのみ有効です。これらはコンパイラの最適化によって生成され、多くのコンパイラがそれらを生成します(ベクトル関数のクラス全体がこのカテゴリに入ります)。

この広大な多様性に直面して、Cのデザイナーはちょうどどこかでそれをカットしなければなりませんでした。そして、(+、 - 、〜、&、|、& &、||などのような単純な演算子として表現できるものを提供することを選択しましたが、swap()関数のような関数呼び出し構文を必要とするものは何も提供しませんでした。あなたは提案する。

関連する問題