x86 アセンブリに関するウィキペディアの記事には、「プログラマは IP レジスタに直接アクセスできない」と書かれています。
直接とは、mov や add などの命令を使用することを意味します。
なぜだめですか?この背後にある理由は何ですか? 技術的な制限は何ですか?
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 の可能な設計でした。ARM は、読み取り/書き込み用のプログラム カウンターを R15 として公開します。しかし、それは珍しいことです。
これにより、非常にコンパクトな関数のプロローグ/エピローグが可能になり、1 つの命令で複数のレジスタをプッシュまたはポップする機能 ( push {r5, lr}
開始時とpop {r5, pc}
復帰時) が可能になります。(リンク レジスタの保存された値をプログラム カウンタにポップする)。
ただし、高パフォーマンス/順不同の ARM 実装の利便性が低下するため、AArch64 では削除されました。
可能ですが、レジスタの 1 つを使い果たします。32 ビット ARM には 16 個の整数レジスタ (PC を含む) があるため、レジスタ番号は ARM マシン コードでエンコードするのに 4 ビットかかります。別のレジスタはほとんどの場合、スタック ポインタとして結び付けられているため、ARM には 14 個の汎用整数レジスタがあります。(LRはスタックに保存できるため、関数本体内の汎用レジスタとして使用できます)。
最新の x86 のほとんどは 8086 から継承されています。かなりコンパクトな可変長命令エンコーディングで設計されており、8 つのレジスタしかなく、マシン コードの各 src および dst レジスタに 3 ビットしか必要としません。
オリジナルの 8086 では、それらはあまり汎用的ではなく、SP 相対アドレッシングは 16 ビット モードでは不可能であるため、本質的に 2 つのレジスタ (SP と BP) がスタック スタッフに結び付けられています。これにより、ある程度汎用的なレジスタが 6 つしか残されず、そのうちの 1 つを汎用ではなく PC にすると、使用可能なレジスタが大幅に減少し、典型的なコードでのスピル/リロードの量が大幅に増加します。
AMD64 では、r8-r15 と RIP 相対アドレッシング モードが追加されました。 lea rsi, [rip+whatever]
、および静的データと定数に直接アクセスするための RIP 相対アドレッシング モードだけで、効率的な位置に依存しないコードを作成できます。RIP への書き込みには、間接的な JMP 命令で十分です。
整数レジスタと間接ジャンプでいつでも同じことができるので、任意の命令を使用して PC を読み書きできるようにしても、実際には何も得られません。x86-64 の R15 が RIP と同じであることは、特にコンパイラ ターゲットとしてのアーキテクチャのパフォーマンスにとって、ほぼ純粋な欠点です。(手書きの asm の奇妙なものは、AMD64 が設計された 2000 年までには、すでに非常に珍しいニッチなものでした。)
つまり、AMD64 は、x86 が ARM のように完全に公開されたプログラム カウンターを獲得できた初めてのケースですが、それを行わない十分な理由がたくさんありました。
jmp
will set the EIP
register.
this code will set eip to 00401000:
mov eax, 00401000
jmp eax ;set Eip to 00401000
and for getting EIP
call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret
他のレジスタにアクセスするのと同じ方法で IP レジスタに直接アクセスできないことを意味していたと思います。プログラマーは、たとえばジャンプ命令を発行することによって、確実に IP に書き込むことができます。