|
Assembly dili öğrenirken aşağıdaki kodu bulduğumda, programın normal şekilde bitemeyeceğini düşündüm. Ancak, hata ayıklama tek adımlı takip sonrası programın normal şekilde sona erebileceği tespit edildi ve garip bir olgu ortaya çıktı: program code:0005'ten code:0014'e çalışmaya başladığında, jmp komutuyla code:0008'e atlamaya devam etti. Ancak, bir adım ileriye devam ettiğinde, program doğrudan code:0018 yerine code:0'a (yani S1 segmenti) atlar. İlk başta ne olduğunu anlamadım ama birçok tek adımlı gözlemden sonra hâlâ garip hissettim. Ders kitabındaki JMP talimatlarının kullanımını dikkatlice inceledikten ve ardından programı makine kodu ile birleştirdikten sonra, JMP talimatları hakkında yeni bir anlayış kazandım. kod adresi ofseti (IP) makine komutlarını birleştirme CS:Code (birim: h) varsayım kod segmenti mov ax, 4c00h 0000 B8004C int 21h 0003 CD21 start: mov ax,0 0005 B80000 S: Nop 0008 90 Nop 0009 90 mov di,offset s 000A BF0800 mov si, offset s2 000D BE2000 mov ax,cs:[si] CS:0020=F6EB mov cs:[di],ax CS:0008=9090 s0: jmp kısa s 0016 EBF0 S1: mov ax, 0 0018 B80000 int 21h 001B CD21 mov ax,0 001D B80000 S2: JMP Kısa S1 0020 EBF6 Nop 0022 90 kod sonu Başlangıç bitti 1. Aşağıdaki iki nokta net şekilde anlaşılmalıdır 1. CPU komutlarının yürütülme süreci şu şekildedir: <1>. CS:IP tarafından işaretlenen bellek ünitesinden komutu okuya ve komut tamponuna koyun. <2>. IP=IP+Şu anda tampona okunan komutun uzunluğu, yani IP bir sonraki komuta işaret eder. <3>. Mevcut komutu tamponda çalıştırın. <1. adıma geç> 2. İç segmenti aktarmak için jmp kısa komutunun anlamı <1>. IP, IP'deki ofsettir, yani IP = tanımlayıcıdaki adres - jmp komutundan sonraki ilk baytın adresi. <2>. Bu komutun işlevi, IP'nin değerini değiştirmektir ve komut yürütüldükten sonra IP = IP + 8 bit ofset < 3> ve 8 bitlerin yer değiştirme aralığı -128~127 ve bu kayma, tamamlayıcı şeklinde ifade edilir [2]. 2. Kod analizi 1. Adım 1: Program giriş başlangıcından (code:0005) çalıştırmaya başlar, code:0013~0014 ifadesi çalıştırıldığında, S2 etiketindeki jmp short S1 ifadesinin makine kodu code:0008 olarak kopyalanır ve IP 0016 olur. Bu aşamada, jmp short s komutu yoksa, program s2:jmp short s1 olarak çalıştırılacak, jmp short s1 komut tamponuna okunacak ve IP=0022; ve s2'den s1'e aktarım segment içi transferdir, makine kodu formatı EB disp ve disp=designation s1-designation s2=(00018-0022) complement=F6 olur, yani jmp short s1 komutunun makine kodu EBF6 olmalıdır. Bu nedenle, EBF6 code:0008~code:0009 birimine kopyalanır. 2. Adım 2: Komut jmp short s (EBF0) komutunu komut tamponuna okun, IP=IP+0002=0018; s-tanımlamasının tamamlayıcı kodu s0=(0008-0018) = F0, s0'dan s'ye aktarım segment içi transferdir ve makine kodu formatı EB disp (yani EBF0) olarak belirlenir 3. Adım 3: jmp short s(EBF0) komutu, EBF0 komutunu çalıştırdıktan sonra, IP=IP+(s-designation s0)=0008 komutunu çalıştırdıktan sonra kod:0008 birimine işaret eden bir komuttur. 4. Adım 4: Birim kodu:0008'in içeriğini okuyun. S2'deki jmp short s1 (EBF6) komutu code:0008~code:0009 ünitesine kopyalandığından, birimin içeriği okunduktan sonra IP=IP+0002=000A 5. Adım 5: Komut jmp short s1 (EBF6), EBF6 komutunu çalıştırdıktan sonra IP'yi değiştirmek için bir komuttur, IP=IP+(s1-designation s2)=0000 komutu code:0000 birimine işaret eder. 6. Adım 6: Program code:0000 içine geçer ve çalıştırılır, yani normal son tamamlanır. 3. Son Yazı Bu kodu doğru şekilde analiz edin: CPU komut yürütme sürecini ve jmp kısa süresini anlamak mı gerekiyor? (IP modifikasyonuyla hesaplanmıştır). Ayrıca, ofset hesaplama sonucunun tamamlayıcı kodu da bir anahtardır. Bu görünüşte anormal kodu analiz ettikten sonra, montajdaki JMP talimatlarını daha derinlemesine anladım.
|