İhtiyacınız olan ilk şey bu dosya gibi bir şey . Bu NASM montajcı tarafından kullanılan x86 işlemciler için talimat veritabanı (ki aslında talimatları çeviren parçalar olmasa da, yazmaya yardımcı oldum). Veritabanından rastgele bir satır seçelim:
ADD rm32,imm8 [mi: hle o32 83 /0 ib,s] 386,LOCK
Bunun anlamı, talimatı tanımlamasıdır ADD
. Bu komutun birden fazla varyantı vardır ve burada tarif edilen spesifik, 32 bitlik bir kayıt veya bellek adresi alan ve hemen 8 bitlik bir değer ekleyen varyanttır (yani talimatta doğrudan dahil edilen bir sabit). Bu sürümü kullanacak örnek bir montaj talimatı şudur:
add eax, 42
Şimdi, metin girişinizi almanız ve bireysel talimatlara ve işlenenlere ayrıştırmanız gerekir. Yukarıdaki talimat için, bu muhtemelen talimatı içeren bir yapıya ADD
ve bir işlenen dizisine (kayıt EAX
ve değere referans 42
) neden olacaktır. Bu yapıya sahip olduğunuzda, talimat veritabanını çalıştırırsınız ve hem komut adı hem de işlenen türleriyle eşleşen satırı bulursunuz. Bir eşleşme bulamazsanız, bu, kullanıcıya sunulması gereken bir hatadır ("opcode ve işlenenlerin yasadışı kombinasyonu" veya benzeri, normal metindir).
Veritabanından satır aldıktan sonra, bu talimat için üçüncü sütuna bakıyoruz:
[mi: hle o32 83 /0 ib,s]
Bu, gerekli makine kodu talimatının nasıl oluşturulacağını açıklayan bir dizi talimattır:
- Bu
mi
, işlenenlerin bir tanımlamasıdır: bir a modr/m
(kayıt veya bellek) işleneni (yani modr/m
, talimatın sonuna bir bayt eklememiz gerekeceği anlamına gelir, daha sonra geleceğiz) ve bir acil talimat ( talimatın açıklamasında kullanılmalıdır).
- Sıradaki
hle
. Bu, "kilit" önekini nasıl ele aldığımızı tanımlar. "Kilit" kullanmadık, görmezden geldik.
- Sıradaki
o32
. Bu bize 16 bit çıkış biçimi için kod monte edersek, talimatın işlenen boyut geçersiz kılma önekine ihtiyacı olduğunu söyler. 16-bit çıktı üretiyor olsaydık, şimdi öneki ( 0x66
) üretirdik , ama öyle olmadığımızı ve devam edeceğimizi varsayacağım.
- Sıradaki
83
. Bu, onaltılı olarak gerçek bir bayttır. Biz çıkardık.
Sıradaki /0
. Bu, modr / m bytem içinde ihtiyaç duyacağımız bazı ekstra bitleri belirtir ve üretmemize neden olur. modr/m
Bayt kodlamak kayıtları veya dolaylı bellek başvuruları için kullanılır. Tek bir işlenen var, bir sicil. Kayıt başka bir veri dosyasında belirtilen bir numaraya sahiptir :
eax REG_EAX reg32 0
reg32
Orijinal veritabanından gerekli talimat boyutunu kabul edip etmediğini kontrol ediyoruz (öyle). 0
Kasan sayıdır. Bir modr/m
bayt işlemcisi tarafından belirlenen bir veri yapısı, böyle bu görünüm olup:
(most significant bit)
2 bits mod - 00 => indirect, e.g. [eax]
01 => indirect plus byte offset
10 => indirect plus word offset
11 => register
3 bits reg - identifies register
3 bits rm - identifies second register or additional data
(least significant bit)
Bir sicille çalıştığımız için, mod
alan öyle 0b11
.
reg
Tarla, Kullandığımız kayıt sayısıdır0b000
- Bu talimatta yalnızca bir kayıt olduğundan,
rm
alanı bir şeyle doldurmamız gerekiyor . Belirtilen ekstra veriler bunun /0
içindi, bu yüzden bunu rm
alana koyduk 0b000
.
- Bu
modr/m
nedenle bayt 0b11000000
veya 0xC0
. Bunun çıktısını alıyoruz.
- Sıradaki
ib,s
. Bu, imzalı bir anlık baytı belirtir. İşlenenlere bakarız ve hemen bir değere sahip olduğumuzu not ederiz. İşaretli bir bayta dönüştürüyoruz ve çıktısını veriyoruz ( 42
=> 0x2A
).
Tamamen montajlı talimat nedenle: 0x83 0xC0 0x2A
. Baytların hiçbirinin bellek referansı oluşturmadığını (çıkış modülünün çalışıp çalışmadığını bilmeleri gerekebilir) bir notla birlikte çıkış modülünüze gönderin.
Her talimat için tekrarlayın. Referans alındığında ne ekleyeceğinizi bilmeniz için etiketleri takip edin. Nesne dosyası çıkış modüllerinize aktarılan makrolar ve yönergeler için olanaklar ekleyin. Temel olarak bir montajcı bu şekilde çalışır.