1 puan yazan GN⁺ 2024-07-11 | 1 yorum | WhatsApp'ta paylaş

x86 emülatörü yazarken öğrendiğim tuhaf şeyler

  • x86 ve amd64 emülatörleri yazarken öğrenilen çeşitli trivia ve tuhaf noktalardan bahsediliyor
  • Time Travel Debugging(TTD), bir sürecin yürütülmesini komut düzeyinde kaydetmek için CPU emülatörü kullanıyor
  • TTD'nin ilk sürümü iDNA olarak adlandırılıyordu; assembly ile yazılmıştı, hızlıydı ama bakımı zordu
  • İkinci sürüm C++ ile yazıldı ve bakım kolaylığı artırıldı

İşe yaramaz x86 kodlama trivia'ları

  • x86 kodlama şeması, aynı komutun birden fazla şekilde kodlanmasına izin veriyor
  • int 3 komutu CD 03 veya CC olarak kodlanabiliyor
  • EAX yazmacına "akümülatör yazmacı" denir ve kodlamada gerçekten bir farkı vardır
  • REX öneki, 64 bit kodda daha geniş bir yazmaç aralığına erişim sağlar
  • Komutlar en fazla 15 bayt uzunluğunda olabilir; bu sınır aşılırsa bir istisna oluşur
  • Adres override öneki, 64 bit modda 32 bit adreslere başvurabilmeyi sağlar

Tuhaf bayrak özellikleri

  • INC komutu, ADD komutundan farklı olarak taşıma bayrağını güncellemez
  • CMPXCHG8B/CMPXCHG16B komutları yalnızca sıfır bayrağını değiştirir
  • Kaydırma ve döndürme komutları, kaydırma miktarı 1'den büyükse taşma bayrağını tanımsız durumda bırakır

Kaydırma komutlarında daha fazla sürpriz

  • shr ax, 10h, ax yazmacını 16 bit kaydırarak 0 yapar
  • shr eax, 20h, eax yazmacını 32 bit kaydırır ama değer değişmez
  • Kaydırma miktarı 1FH ile maskelenir

Segment override

  • Segmentler 32 bit ve 64 bit kodda hâlâ kullanılır; başlıca kullanım alanı thread-local storage'dır
  • Windows'ta FS veya GS yazmaçları TEB(Thread Execution Block)'e başvurmak için kullanılır
  • 32 bit süreçlerde FS, 64 bit süreçlerde ise GS kullanılır
  • 64 bit modda segment yazmaçlarının değeri önemli değildir

Segment override: daha fazla trivia

  • 32 bit modda segment yazmacının gerçek değeri segment descriptor'üne başvurur
  • 64 bit modda base, MSR tarafından kontrol edilir
  • WinDbg'de 64 bit bir sürecin segment değerleri doğrudan okunamaz

Sonuç

  • Bu yazı, x86 trivia'larından oluşan rastgele bir liste sunuyor
  • Emülatör yazmak, CPU'nun nasıl çalıştığını derinlemesine anlamaya yardımcı oluyor
  • Agner Fog'un web sitesinde harika kaynaklar bulunabilir

GN⁺ özeti

  • x86 ve amd64 emülatörleri yazarken öğrenilen çeşitli trivia ve tuhaf noktalar anlatılıyor
  • Emülatör yazmak, CPU'nun çalışma biçimini derinlemesine anlamaya yardımcı oluyor
  • int 3 komutunun farklı kodlamaları, REX öneki, segment override gibi çeşitli trivia'lar ele alınıyor
  • Daha fazla kaynak için Agner Fog'un web sitesine bakılabilir

1 yorum

 
GN⁺ 2024-07-11
Hacker News görüşü
  • Intel SDM, BSF/BSR komutlarında giriş 0 olduğunda hedef değerinin tanımsız olduğunu açıkça belirtiyor. AMD ise bu durumda hedefin değiştirilmediğini belgeliyor
    • glibc, Intel’de hedefin değiştirilmediğine dair resmî olmayan gerçeği kullanıyor
    • TZCNT/LZCNT, BSF/BSR’nin F3 öneki eklenmiş biçimi ve eski işlemcilerde bu önek yok sayılıyor. Aynı kod farklı CPU’larda farklı çalışabilir
  • Öneklerle ilgili çok şikâyet var, ancak en büyük sorun bu değil. REX/VEX/EVEX.RXB genişletme bitleri uygulanmadığında yok sayılıyor
    • APX’te REX2 öneki r16-r31 kayıtlarını kodlayabiliyor, ancak xmm16-xmm31 için bu mümkün değil
    • EVEX öneki, birçok opcode’a göre farklı yerleşim düzenine sahip
    • Kayıt türüne göre genişletme bitlerinin kullanımı değişiyor
  • Assembly kodlamayı seven birinin görüşü. Basit ve dikey estetik niteliğinden hoşlanıyor
    • JS kullanan bir arkadaşına stack’i anlatmak için mini bir VM yazma deneyimini paylaşıyor
    • Arkadaşının web geliştirmeyle meşgul olduğu için derinlemesine çalışmaya vakit bulamadığını belirtiyor
  • Salsa20 varyantı ve makine kodunun cryp.to’da olduğunu yanlış hatırlamış. Dan Berstein’ın sitesi cr.yp.to
    • Bir startup’ta veri şifreleme üzerine çalışırken çeşitli implementasyonları test etme deneyimini paylaşıyor
  • Justine Tunney ve onun emülatörünü tavsiye ediyor. Dokümantasyon CPU’nun nasıl çalıştığını iyi açıklıyor
  • CPU emülatörü yazmanın CPU’yu anlamanın en iyi yolu olduğu görüşüne karşı çıkıyor
    • Gate seviyesinde CPU yapmanın daha iyi bir yöntem olduğunu savunuyor
  • x86 assembly’nin RISC’ten daha fazla sorun çıkardığı görüşüne karşı çıkıyor
    • x86’ın analiz edilmesi kolay, ancak MIPS zor
  • x86 işlemci emülatörü geliştiricilerine saygısını ifade ediyor
    • i386 emülatörü geliştirirken sistem çağrıları ve ELF hakkında çok şey öğrendiğini söylüyor
  • x86 emülatörü yazma deneyimini paylaşıyor
    • İlk BIOS kodunu çalıştıran oyuncak bir emülatör yazdığı zamanı hatırlıyor
  • Blog stilini ve düzenini beğendiğini söylüyor