命令ポインターを直接設定できないのはなぜですか?
-
26-10-2019 - |
質問
x86アセンブリに関するウィキペディアの記事 「IPレジスタに直接アクセスできない」と述べています。
直接は、movやaddなどの指示を意味します。
なぜだめですか?この背後にある理由は何ですか?技術的な制限は何ですか?
解決
正当なユースケースがないため、直接アクセスできません。任意の指示の変更があります eip
ブランチの予測を非常に困難にし、おそらく多くのセキュリティ問題を開くでしょう。
編集できます eip
使用 jmp
, call
また ret
. 。直接読み取ったり、書いたりすることはできません eip
通常の操作を使用します
設定 eip
登録簿と同じくらい簡単です jmp eax
. 。あなたもできます push eax; ret
, 、の値を押し進めます eax
スタックしてから戻ります(つまり、ポップとジャンプ)。 3番目のオプションはです call eax
EAXの住所への呼び出しを行います。
読書は次のように行うことができます:
call get_eip
get_eip:
pop eax ; eax now contains the address of this instruction
他のヒント
それはx86の可能なデザインだったでしょう。腕はそうします R15として読み取り/書き込みのプログラムカウンターを公開する. 。しかし、それは珍しいことです。
非常にコンパクトな機能プロローグ/エピローグと、単一の命令で複数のレジスタをプッシュまたはポップする機能を可能にします。 push {r5, lr}
エントリーで、そして pop {r5, pc}
戻る。 (リンクレジスタの保存された値をプログラムカウンターにポップします)。
ただし、高PERF /オーダーアウトアームの実装が便利ではなく、AARCH64のためにドロップされました。
そう それは可能ですが、レジスタの1つを使用します. 。 32ビットアームには16の整数レジスタ(PCを含む)があるため、レジスタ番号にはアームマシンコードでエンコードするのに4ビットがかかります。別のレジスタはほとんど常にスタックポインターとして結び付けられているため、アームには14の汎用整数レジスタがあります。 (LRはスタックに保存できるため、関数本体内の汎用レジスタとして使用できます。
最新のX86のほとんどは8086から継承されています。これは、かなりコンパクトな可変長さの命令エンコードで設計され、マシンコードの各SRCおよびDSTレジスタに3ビットのみを必要とする8つのレジスタのみが設計されています。
元の8086では、それらはそれほど汎用的ではなく、16ビットモードではSP相関アドレス指定が不可能であるため、基本的に2つのレジスタ(SPとBP)がスタックのために縛られています。これにより、ややジェネラルの目的登録が6つしか残りません。そのうちの1つを汎用の代わりにPCにすることは、利用可能なレジスタを大幅に削減し、典型的なコードの流出/リロードの量を大幅に増やします。
AMD64はR8-R15を追加し、RIP相関アドレス指定モードを追加しました。 lea rsi, [rip+whatever]
, 、および静的データと定数に直接アクセスするためのRIP相関アドレス指定モードは、効率的な位置に依存しないコードに必要なすべてです。間接的なJMP命令は、リッピングするのに完全に十分です。
整数レジスタと間接的なジャンプでいつでも同じことを行うことができるため、任意の指示をPCの読み取りまたは書き込みに使用することで、実際に得られるものは何もありません。 X86-64のR15がRIPと同じものであること、特にコンパイラターゲットとしてのアーキテクチャのパフォーマンスでは、ほぼ純粋な欠点があります。 (AMD64が設計された2000年までに、手書きのASMの奇妙なものは、すでに非常に珍しいニッチなものでした。)
したがって、AMD64は、X86がARMのような完全に露出したプログラムカウンターをもっともらしく獲得できたのは初めてですが、それをしない理由はたくさんありました。
彼らは、他のレジスタにアクセスするのと同じ方法で、IPレジスタに直接アクセスできないことを意味したと思います。プログラマーは、たとえばジャンプ命令を発行することにより、間違いなくIPに書き込むことができます。
jmp
を設定します EIP
登録。
このコードは、EIPを00401000に設定します。
mov eax, 00401000
jmp eax ;set Eip to 00401000
そして、取得するために EIP
call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret