Страница 5 из 6 Особенности и ошибки дизассемблера DisDoc 2.3 К сожалению, DisDoc 2.3 совершает ошибки, иногда регулярные, а иногда редкие, коварные и даже подлые. Самая противная ошибка - случайный пропуск данныхвстречается довольно редко. Начнем с того, что встречается очень часто. 1. EQU - кто тебя выдумал? В коде, выданном дизассемблером, часто попадаются такие загадочные куски: ;<00465> s12 proc near d0046cequ00046ch cmpbx,5ah;00465
Каков смысл присвоения d0046c equ 00046ch ? Чтобы выяснить это, нужно отыскать d0046c в тексте. В нашем случае элемент данных d0046c встречается очень далеко от своего первого появления - в подпрограмме s321 movax,0040h;06257 ;<es = 0040> moves,ax;0625a moval,BYTE PTR es:d0046c;0625c sti ;06260;Turn ON Interrupts b06261:cmpal,BYTE PTR es:d0046c;06261 jzb06261 ;06266;Jump if equal (ZF=1) moval,BYTE PTR es:d0046c;06268 deccx;0626c jnzb06261 ;0626d;Jump not equal(ZF=0) popax;0626f out61h,al ;06270;060-067:8024 keybrd contrlr ;<es = 0000> popes;06272 ret;06273 s321 endp Рис.6 При виде этого текста возникает догадка, что здесь идет зваимодействие с областью данных BIOSa . Действительно, в регистр es засылается число 40, т.е. es будет указывать на адрес 400 - начало этой области. Тогда следующий вопрос - каков смысл адреса 046сh? Легко выяснить, что по этому адресу находится счетчик прерываний от таймера. Если это так, то фрагмент, приведенный на рис.6, обретает смысл - он дает задержку на число прерываний от таймера, заданное в регистре cx. Но если все сказанное верно, то d0046c должно быть равно не 46сh, а просто 6сh! И действительно, если посмотреть подпрограмму s321 отладчиком, то станет ясно, что вместо mov al,BYTE PTR es:d0046c в тексте должно стоять mov al,6ch. Итак, чтобы исправить эту ошибку, необходимо: Удалить из начала подпрограммы s12 присвоение d0046c equ00046ch Переписать приведенный на рис.6 фрагмент s321 следующим образом: movax,0040h;06257 ;<es = 0040> moves,ax;0625a moval,BYTE PTR es:006ch;0625c sti ;06260;Turn ON Interrupts b06261:cmpal,BYTE PTR es:006ch;06261 jzb06261 ;06266;Jump if equal (ZF=1) moval,BYTE PTR es:006ch;06268 deccx;0626c jnzb06261 ;0626d;Jump not equal(ZF=0) popax;0626f out61h,al ;06270;060-067:8024 keybrd contrlr ;<es = 0000> popes;06272 ret;06273 s321 endp Рассмотрим второй пример. В коде, выданном дизассемблером, встретился такой кусок: ;<0074e> s22 proc near d0076aequ00076ah d00771equ000771h calls24 ;<00791>;0074e ............... b0076a:pushcx;0076a calls25 ;<0086b>;0076b calls23 ;<00776>;0076e popcx;00771 decbx;00772
Поиск элемента данных d0076a окончился неудачей. А d00771 встретился в таком фрагменте: ..................................... movBYTE PTR ds:b0076a,51h;0080b movBYTE PTR ds:d00771,59h;00810 ......................................
Здесь явно идет модификация кода подпрограммы s22. Значит, необходимо заменить d00771 на b00771, пометить этой меткой соответствующую инструкцию в s22 и удалить присвоения d0076a equ00076ah d00771 equ000771h
Исправленный фрагмент s22 будет выглядеть так: ;<0074e> s22 proc near calls24 ;<00791>;0074e ...................................................... b0076a:pushcx;0076a calls25 ;<0086b>;0076b calls23 ;<00776>;0076e b00771:popcx;00771 decbx;00772 .............................................. movBYTE PTR ds:b0076a,51h;0080b movBYTE PTR ds:b00771,59h;00810 ................................................
Рассмотрим еще один пример. В начале s32 встретились уже знакомые псевдооператоры: ;<00bf7> s32 proc near d00c1cequ000c1ch d00c1eequ000c1eh
Если посмотреть в область со смещениями, близкими к с1с, то там окажется кусок повисшего кода, который может быть только данными: ....................................... oral,BYTE PTR [bp+di];00c14 addWORD PTR [bx+di],ax;00c16 addBYTE PTR [bx+si],al;00c18 addBYTE PTR [bx+si],al;00c1a movdi,1306h;00c1c addax,06c0h;00c1f ......................................
Теперь нужно поискать идентификаторы d00c1c и d00c1e в тексте, выданном дизассемблером. Очень быстро можно найти фрагменты типа: mov WORD PTR ds:d00c1c,ax, mov WORD PTR ds:d00c1e,ax. Значит, ошибка дизассемблера состоит в том, что он перепутал данные и команды и на этой почве сделал два неправильных присваивания, equ, попавших в начало подпрограммы s32. Исправления будут заключаться в следующем: Убрать из начала подпрограммы s32 два псевдооператора equ. Переписать коды на рисунке 7 следующим образом: d00c14db 0a,03,01,01,00,00,00,00 ;00c14 d00c1cdb 0bf,06 ;00c1c d00c1e db 13,05,0c0,06 ;00c1e
В заключение рассмотрим совсем простенький фрагмент кода: ;<01252> s39 proc near d0125dequ00125dh d0125fequ00125fh decbh;01252 jzb0124f ;01254;Jump if equal (ZF=1) xorah,ah;01256 shlal,1 ;01258;Multiply by 2's rclah,1 ;0125a;CF<--[HI .. LO]<--CF ret;0125c ;----------------------------------------------------- addBYTE PTR [bx+si],al;0125d addBYTE PTR [bx+si],al;0125f s39 endp Укажем без комментариев, что подпрогромма s39 должна выглядеть так: ;<01252> s39 proc near decbh;01252 jzb0124f ;01254;Jump if equal (ZF=1) xorah,ah;01256 shlal,1 ;01258;Multiply by 2's rclah,1 ;0125a;CF<--[HI .. LO]<--CF ret;0125c ;----------------------------------------------------- d0125ddb 00,00 ;0125d d0125fdb 00,00 ;0125f s39 endp
В заключение этого пункта подведем итоги. Значки equ называют всевдооператорами. Если говорить о дизассемблере DisDoc 2.3, то это название удивительно точное. Если в тексте встретится equ - то ошибка рядом. Между тем, иногда DisDoc 2.3 употребляет equ вполне корректно. Так что будьте бдительны и не дайте себя обмануть. |