2017-03-22 6 views
0

小さなメモリモデルでは、セグメントレジスタは同じ値を保持しています。 (%fs、%gsを除く)。ここには相対的なトピックがあります: Segment prefix when using pointers as function parameters。 しかし、セグメントレジスタの値が異なる場合はどうなりますか?例えば、我々は、ポインタを介して関数にアドレスを渡すことができる:セグメントプレフィックスmov/leaを登録する方法は?

mov %fs:(%rax),%rsi 
mov %ds:(%rax),%rsi 

%fs%dsを考慮し、異なるベースアドレスを保持しています。また、関数は両方の種類の参照を使用できます。機能は区別できますか?%rsiは実際に登録されていますか?あるいは状況は存在しないのですか? x64の下

ss
+0

x86_64の「小さなメモリモデル」とは何ですか?これは16bモードでこのように使用されましたが、セグメント値は物理アドレスの一部です(最後の20bアドレスのビット4〜19に追加されます)。 |あなたがそのようなコードにポインタを渡す方法は明らかではない( 'rax'では?)、 'fs'が' ds'と異なるならば、それぞれの 'mov'は異なる論理メモリアドレスを使用します(メモリはそのようにマップされていれば同じ物理アドレスにマッピングされますが、最初の 'fs:rax'、他の' ds:rax' ...何かがx86_64(ディスクリプタテーブルへの何らかのインデックス?)で意味するもの) – Ped7g

+0

どちらのアセンブリステートメントも場所から64ビットの値を読み込みますメモリに格納し、RSIに格納します。いずれのステートメントも、その関数のアドレスが以前に読み取られた場所に格納されていない限り、関数のアドレスをRSIにロードしません。第1の命令によって読み取られるメモリ内の位置は、線形アドレス「FS.base + RAX」であり、ここで、「FS.base」はFSセグメントのベースである。第2のメモリによって読み取られるメモリ内の位置は、線形アドレス「RAX」にある。 DSセグメントのベースは、64ビットモードでは常に0です。 –

+0

@ Ped7g別のトピックで「小さなメモリモデル」を見たとき、セグメントレジスタが同じ値を共有していることを意味します。実際には、アドレスが1つのレジスタから渡されるため、関数がどのセグメントレジスタを使ってデータにアクセスすべきかを知っています。私はコードが混乱して申し訳ありません... – liubenxi

答えて

2

csdsesセグメント全てがfsgsセグメントは、異なる目的のために使用される0
で同じ値を保持します。現在のプロセスの32ビットスレッド情報ブロックに

のWindows
fsポイント。
gsは、現在のプロセスの64ビットTIBを指します。

Linux 32ビット・カーネルfs
はCPUごとのデータ領域の塩基です。 64ビットカーネルgsでは、pda(プロセッサデータ領域)を指しています。 pdaは 単一構造ですが、per-cpuデータはcpu単位で の変数が配置されるセクションです。

fsは、64ビットオペレーティングシステム(WoW64など)で32ビットコードを実行する場合に使用されます。

特殊な目的を持っていたレジスタはx86でしたが、現在ほとんどのレジスタは汎用です。

rsiは、いかなる目的にも使用できます。
文字列命令でのみ、特別な意味を持ちます。
この文脈では、ソース(例えば、movsb)を指すために使用されます。

それで機能を区別することはできますか?

セグメントプレフィックスをプレフィックスとして使用します。

mov rsi,[rax]  // rsi = memory(rax). 
xor eax,eax  //rax =0 (remember 32 bit instructions zero extend) 
mov rsi,[gs:rax] //load the first 8 bytes of the 64-bit TIB into rsi. 


LEAについてリーは、それが単にフラグを変更せずに計算を行い、メモリにアクセスしません。
多くの場合、これらの計算にはポインタの計算が含まれますが、一般的な算術演算でもあります。
セグメントプレフィックスをleaの前に置くことは意味をなさないので効果はありません。

+0

どのオペレーティングシステムですか? Windowsの場合、rand()のシード値などのスレッド値の少なくともいくつかは、fs:...からスレッドの仮想アドレス空間にマップされ、その後は通常のポインタを使用できます。プロセス内のスレッドは仮想アドレス空間を共有するため、各スレッド変数は異なるポインタ値を使用してアクセスされます。 – rcgldr

+0

'[gs:rax]'と '[ds:rcx]'が実際に同じリニアアドレスを保持していても、関数は2つのコードで別々に扱わなければなりません。 – liubenxi

+0

はい、それは正しいです。 – Johan

関連する問題