1 ポイント 投稿者 GN⁺ 2024-07-11 | 1件のコメント | WhatsAppで共有

x86エミュレータを書きながら学んだ奇妙なこと

  • x86およびamd64エミュレータを書きながら学んだ、さまざまなトリビアや奇妙な点について説明している
  • Time Travel Debugging(TTD)ではCPUエミュレータを使って、プロセスの実行を命令レベルで記録する
  • 最初のバージョンのTTDはiDNAと呼ばれ、アセンブリコードで書かれていたため高速だったが、保守が難しかった
  • 2番目のバージョンはC++で書かれ、保守性が向上した

役に立たないx86エンコーディングのトリビア

  • x86のエンコーディング方式では、同じ命令を複数の方法でエンコードできる
  • int 3命令はCD 03またはCCとしてエンコードできる
  • EAXレジスタは「アキュムレータレジスタ」と呼ばれ、エンコーディング上も実際に違いがある
  • REXプレフィックスは64ビットコードで、より広い範囲のレジスタにアクセスできるようにする
  • 命令は最大15バイトまで長くでき、これを超えると例外が発生する
  • アドレスオーバーライドプレフィックスは、64ビットモードで32ビットアドレスを参照できるようにする

奇妙なフラグの特性

  • INC命令はADD命令と異なり、キャリーフラグを更新しない
  • CMPXCHG8B/CMPXCHG16B命令はゼロフラグだけを変更する
  • シフトおよびローテート命令は、シフト量が1より大きい場合、オーバーフローフラグを未定義のままにする

シフト命令のさらなる驚き

  • shr ax, 10haxレジスタを16ビット分シフトして0にする
  • shr eax, 20heaxレジスタを32ビット分シフトするが、値は変化しない
  • シフト量は1FHでマスクされる

セグメントオーバーライド

  • セグメントは32ビットおよび64ビットコードでも依然として使われており、主にスレッドローカルストレージに使われる
  • WindowsではFSまたはGSレジスタを使ってTEB(Thread Execution Block)を参照する
  • 32ビットプロセスではFSを使い、64ビットプロセスではGSを使う
  • 64ビットモードではセグメントレジスタの値は重要ではない

セグメントオーバーライド: さらに多くのトリビア

  • 32ビットモードでは、セグメントレジスタの実際の値がセグメントディスクリプタを参照する
  • 64ビットモードでは、ベースはMSRによって制御される
  • WinDbgでは64ビットプロセスのセグメント値を直接読むことはできない

結論

  • この記事はx86トリビアのランダムな一覧を提供している
  • エミュレータを書くことは、CPUがどのように動作するかを深く理解する助けになる
  • Agner Fogのウェブサイトで優れたリソースを確認できる

GN⁺のまとめ

  • x86およびamd64エミュレータを書きながら学んだ、さまざまなトリビアや奇妙な点を説明している
  • エミュレータを書くことは、CPUの動作方式を深く理解する助けになる
  • int 3命令のさまざまなエンコード方法、REXプレフィックス、セグメントオーバーライドなど、さまざまなトリビアを扱っている
  • Agner Fogのウェブサイトでさらに多くのリソースを確認できる

1件のコメント

 
GN⁺ 2024-07-11
Hacker Newsのコメント
  • Intel SDM では、BSF/BSR 命令に 0 を入力した場合、宛先の値は未定義であると明記されている。AMD はこの場合、宛先は変更されないと文書化している
    • glibc は、Intel でも宛先が変更されないという非公式の事実を利用している
    • TZCNT/LZCNT は BSF/BSR に F3 プレフィックスが付いた形で、旧型プロセッサでは無視される。同じコードでも CPU によって異なる動作をする可能性がある
  • プレフィックスへの不満は多いが、これは最大の問題ではない。REX/VEX/EVEX.RXB 拡張ビットは、適用されないときには無視される
    • APX では REX2 プレフィックスで r16-r31 レジスタをエンコードできるが、xmm16-xmm31 は不可能である
    • EVEX プレフィックスは、opcode によって異なるレイアウトを持つ
    • レジスタの種類によって拡張ビットの使われ方が異なる
  • アセンブリを書くのを楽しむ人の意見。シンプルで垂直的な美的品質を楽しんでいる
    • JS の友人にスタックを理解させるためにミニ VM を書いた経験を共有している
    • その友人は Web 開発で忙しく、深く学ぶ時間がないことに触れている
  • Salsa20 の派生版とマシンコードが cryp.to にあると誤って覚えていた。Dan Berstein のサイトは cr.yp.to である
    • スタートアップでデータ暗号化関連の作業をしながら、さまざまな実装をテストした経験を共有している
  • Justine Tunney と彼女のエミュレータを勧めている。ドキュメントが CPU の動作方法をうまく説明している
  • CPU エミュレータを書くのが CPU を理解する最良の方法だという意見に反対している
    • ゲートレベルで CPU を作る方がより良い方法だとしている
  • x86 アセンブリが RISC よりも多くの問題を引き起こすという意見に反対している
    • x86 は解析しやすいが、MIPS は難しい
  • x86 プロセッサエミュレータ開発者への敬意を表している
    • i386 エミュレータを開発しながら、システムコールと ELF について多くを学んだ
  • x86 エミュレータを書いた経験を共有している
    • 初期 BIOS コードを実行するおもちゃのエミュレータを書いた経験を振り返っている
  • ブログのスタイルとレイアウトが気に入ったという意見を共有している