web-dev-qa-db-ja.com

リターン指向プログラミングでは、マシンはどのようにアラインされていない命令を実行できますか?

「骨上の無垢な肉のジオメトリ:関数呼び出しなしのlibcへの復帰(x86上)」を読んでいます。

著者は、x86コードは句読点やスペースなしで書かれた英語に似ているため、単語がすべて一緒に実行されると主張しています。これは、プログラマーの意図とは異なる場所で実行を開始できること、および任意の計算を可能にするためにlibc内にこのタイプのコードシーケンスの十分なセットが存在することを意味します。

論文から、次の文は私を混乱させました:

「すべての命令が32ビット長で32ビット境界に揃えられているMIPSのようなアーキテクチャでは、どこから開始または変更するかについて曖昧さはなく、私たちが説明するような意図しない命令もありません。」

32ビットマシンでは、x86命令も32ビットにアラインされていませんか?

これは、非バイナリのアライメントと実行が可能であることを意味しますか? (たとえば、32ビットマシンのメモリにビット「00001111 | 22223333」があり、「11112222」という命令を実行することにしましたか?

1
AOrona

x86はRISCではありません。命令は可変長です。 1から15バイト。もちろん、それらは整列していません。 x86で調整されているものはほとんどありません(アトミック、一部のベクトル命令、キャッシュラインなど)。

あなたが読んでいるテキストは基本的に、命令は別の命令のプレフィックスにはなり得ないが、他のことは何でも行くと言っています。

したがって、メモリに4バイトある場合:AA BB CC DD

命令ポインター(「プログラムカウンター」)がAAを指している場合は、単一の3バイト命令AA BB CCを実行してから、DDからデコードを開始します。しかし、命令ポインタがBBを指している場合、おそらくBB CCも有効な命令です!または、BBだけが有効な1バイト命令です。または、BB CC DDは有効な3バイト命令です。知るか?可能性は無限大。

命令には定数を含めることができるため、定数をJITにフィードできる場合(eBPFプログラムにコンパイルされるファイアウォールルール、ゲームのluaコード、ブラウザーのJavaScriptコードなど)、JITにバイトを使用してコードを生成させることができます必要に応じて、そのコードにジャンプできます(基本的に、定数にジャンプし、CPUがそれを命令、利益として解釈するようにします)。一部のJITは、定数を保持する命令に対して、短い/高速のバイトシーケンスの代わりに「安全な」バイトシーケンスを生成するように注意して、これが発生しないようにします。事前コンパイラについても同じです。

1
Z.T.

命令はx86で整列されていません。

命令がx86で整列されている場合、x86命令はすべて長さが異なるため、これは多くのスペースを浪費します。 1バイトの各命令は、アライメントのためにさらに3バイトを浪費します。

0
user253751