Страница 4 из 6 3. Зависимость от транслятора Программисты на ассемблере склонны пренебрегать правилами хорошего тона, нарушать все мыслимые табу, и это создает дополнительные трудности при дизассемблировании. В качестве примера приведем фрагмент кода, выданного дизассемблером s25proc near inccx;0086b adddi,bp;0086c adcsi,00;0086e adddx,si;00871 pushdi;00873 shldi,1 ;00874;Multiply by 2's adcdx,00;00876 popdi;00879 ret;0087a
Этот фрагмент представляется совершенно невинным, и действительно, он дизассемблирован правильно. Вся беда в том, что программист задумал изменять этот фрагмент, то есть резать по живому. Оказывается, в программе есть еще такой кусок movdi,086bh;007f8 ...................................... movBYTE PTR [di],4ah;00800 movBYTE PTR [di+07],0f1h;00803 movBYTE PTR [di+0ch],0d1h;00807 ...................................... ret;00815
Рис.1 Так как di используется для косвенной адресации, нам прежде всего необходимо заменить 086bh на соответствующий OFFSET d0086b и пометить этой меткой начало подпрограммы s25: s25 proc near d0086b:inccx;0086b ..............................................
Далее следует понять, что делают инструкции, приведенные на рис.1 с подпрограммой s25. Пусть эта подпрограмма асслемблирована с помощью TASM 1.01. Выданный ассемблером код будет таким, как показано на рисунке 2. 41 INC CX 41 INC CX 03FD ADD DI,BP 01EF ADD DI,BP 83D600 ADC SI,0000 83D600 ADC SI,0000 03D6 ADD DX,SI 01F2 ADD DX,SI 57 PUSH DI 57 PUSH DI D1E7 SHL DI,1 D1E7 SHL DI,1 83D200 ADC DX,0000 83D2000 ADC DX,0000 5F POP DI 5F POP DI C3 RET C3 RET
Рис.2 Рис.3 Но вся беда в том, что исходная программа была ассемблирована другим ассемблером и имеет вид, показанный на рисунке 3. Как видно из сравнения рисунков 2 и 3, TASM 1.01 и неизвестный ассемблер транслируют инструкции ADD по-разному, и это приводит к катастрофическим последствиям. Действительно, посмотрим, как воздействует участок кода, показанный на Рис.1 (перед этим заменим 086bh на OFFSET d0086b) на подпрограмму s25, транслируемую TASMом (рис.4) и неизвестным ассемблером (рис.5). 4A DEC DX 4A DEC DX 03FD ADD DI,BP 01EF ADD DI,BP 83D600 ADC SI,0000 83D600 ADC SI,0000 03F1 ADD SI,CX ;!!!! 01F1 ADD CX,SI ;!!!! 57 PUSH DI 57 PUSH DI D1E7 SHL DI,1 D1E7 SHL DI,1 83D100 ADC CX,0000 83D100 ADC CX,0000 5F POP DI 5F POP DI C3 RET C3 RET
Рис.4 Рис.5 Сравнение рисунков 4 и 5 показывает, что логика работы программы меняется в зависимости от того, какой ассемблер применялся. Как выкрутиться из этой ситуации, если нужного ассемблера нет под рукой? Самый простой, но не очень красивый путь - поставить "заплатку". Чтобы можно было использовать TASM, подпрогроамма s25 должна выглядеть так: s25 proc near d0086b:inccx;0086b add di,bp ;0086c adcsi,00;0086e db 01,0f2 ;adddx,si !!!!!! ;00871 pushdi;00873 shldi,1 ;00874;Multiply by 2's adcdx,00;00876 popdi;00879 ret;0087a |