x64で4つの引数レジスタを選択する-UN * X / Win64に共通
x86について覚えておくべきことの1つは、「reg番号」エンコーディングへのレジスタ名が明確でないことです。命令のエンコーディング(MOD R / Mバイト、http: //www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htmを参照)の観点から、レジスタ番号0 ... 7は、この順序で- ?AX
、?CX
、?DX
、?BX
、?SP
、?BP
、?SI
、?DI
。
したがって、戻り値にA / C / D(regs 0..2)を選択し、最初の2つの引数(「クラシック」32ビット__fastcall
規約)を選択するのは論理的な選択です。64ビットへの移行に関する限り、「上位」のレジストリが注文され、MicrosoftとUN * X / Linuxの両方が最初のR8
/ に移行しましたR9
。
心の中でそれを維持する、Microsoftの選択RAX
(戻り値)とはRCX
、RDX
、R8
、R9
(引数[0..3])あなたが選択した場合に理解選択されている4つの引数のレジスタを。
AMD64 UN * X ABIがRDX
以前に選択した理由がわかりませんRCX
。
x64での6つの引数レジスタの選択-UN * X固有
UN * Xは、RISCアーキテクチャ上で、レジスタを渡す引数を伝統的に実行してきました。具体的には、最初の6つの引数に対して(少なくともPPC、SPARC、MIPSはそうです)。これは、AMD64(UN * X)ABI設計者がそのアーキテクチャでも6つのレジスタを使用することを選択した主な理由の1つかもしれません。
あなたが望むのであれば6個のレジスタがで引数を渡すために、それが選択した論理だRCX
、RDX
、R8
およびR9
それらの4のために、他のどの2あなたは選ぶべきですか?
"より高い" regは、それらを選択するために追加の命令プレフィックスバイトを必要とするため、より大きな命令サイズのフットプリントを持っているので、オプションがある場合はそれらを選択したくないでしょう。従来のレジスターの暗黙的な意味のためRBP
、RSP
これらは使用できません。また、RBX
伝統的にUN * X(グローバルオフセットテーブル)で特別な用途があり、AMD64 ABI設計者は不必要に非互換にしたくなかったようです。
エルゴ、唯一の選択肢はRSI
/ RDI
でした。
RSI
/ RDI
を引数レジスタとして使用する必要がある場合、どの引数を使用する必要がありますか?
それらarg[0]
を作るとarg[1]
いくつかの利点があります。cHaoのコメントを参照してください。
?SI
および?DI
文字列命令のソース/デスティネーションオペランドであり、cHaoが述べたように、引数レジスタとしての使用は、AMD64 UN * X呼び出し規約ではstrcpy()
、たとえば、repz movsb; ret
ソース/ターゲットが2つのCPU命令のみで構成されているため、呼び出し元によってアドレスが正しいレジスターに入れられました。特に、低レベルでコンパイラーによって生成された「接着剤」コード(たとえば、構築時に一部のC ++ヒープアロケーターがゼロで埋められるオブジェクト、またはカーネルでゼロで埋められるヒープページを考える)sbrk()
、またはcopy-on-write pagefaults)膨大な量のブロックのコピー/フィルのため、2つまたは3つのCPU命令を保存するために頻繁に使用されるコードに役立ちます。 「正しい」レジスタ。
そうな方法で、UN * XおよびWin64のはそのUN * X「プリペンド」2つの引数、意図的に選ばれた中で唯一異なっているRSI
/ RDI
レジスタ、の4つの引数の自然な選択にRCX
、RDX
、R8
とR9
。
それ以上 ...
UN * XとWindows x64 ABIの違いは、特定のレジスターへの引数のマッピングだけではありません。Win64の概要については、以下を確認してください。
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64とAMD64 UN * Xは、スタックスペースの使用方法も著しく異なります。たとえば、Win64では、args 0 ... 3がレジスターで渡されても、呼び出し元は関数の引数にスタックスペースを割り当てる必要があります。一方、UN * Xでは、128バイト以下が必要な場合は、リーフ関数(つまり、他の関数を呼び出さない関数)でスタックスペースを割り当てる必要さえありません(所有し、使用できます)カーネルコードでない限り、割り当てを行わずに一定量のスタックを作成します(気の利いたバグのソース)。これらはすべて特定の最適化の選択です。それらの理論的根拠のほとんどは、元の投稿者のウィキペディアの参照が参照している完全なABIの参照で説明されています。