|
Когато попаднах на следния код, докато учех асемблер, просто си помислих, че програмата не може да завърши нормално. Въпреки това, след проследяване на грешки по една стъпка, се установи, че програмата може да приключи нормално, и се случи странен феномен: когато програмата започне да се изпълнява от code:0005 към code:0014, тя продължи да скача към code:0008 с командата jmp. Въпреки това, при продължаване на стъпка напред, програмата преминава директно към code:0 вместо code:0018 (т.е. сегмента с обозначение S1). Първоначално не разбирах какво се случва, но след много единични наблюдения все още се чувствах странно. След внимателно изучаване на използването на JMP инструкции в учебника [1], и след това анализ на програмата в комбинация с машинен код, имам ново разбиране за JMP инструкциите. Машинни инструкции за сглобяване на код, адрес офсет (IP) Приемем CS:код (единица: H) Кодов сегмент mov ax, 4c00h 0000 B8004C int 21h 0003 CD21 start: mov ax,0 0005 B80000 С: NoP 0008 90 nop 0009 90 mov di, offset s 000A BF0800 mov si, офсет S2 000D BE2000 mov ax,cs:[si] CS:0020=F6EB mov cs:[di],ax CS:0008=9090 s0: jmp short s 0016 EBF0 s1: MOV AX, 0 0018 B80000 вътрешен 21 ч. 001B CD21 mov ax, 0 001D B80000 s2: JMP къс сезон 1 0020 EBF6 NOP 0022 90 Край на кода край на старт 1. Следващите две точки трябва да бъдат ясно разбрани 1. Процесът на изпълнение на CPU инструкции е следният: <1>. Прочетете инструкцията от паметта, посочена от CS:IP, и я поставете в буфера за инструкции. <2>. IP=IP+Дължината на инструкцията, която в момента се чете в буфера, тоест IP сочи към следващата инструкция. <3>. Изпълни текущата команда в буфера. Премини към стъпка <1> 2. Значението на кратката команда jmp за прехвърляне на вътрешния сегмент <1>. IP е офсетът, тоест адресът на IP = обозначение – адресът на първия байт след командата jmp. <2>. Функцията на тази команда е да променя стойността на IP, а след изпълнение на командата IP = IP + 8-битово отклонение < 3> и 8 бита имат диапазон на изместване -128~127, а отместването се изразява под формата на допълнение [2]. 2. Анализ на кода 1. Стъпка 1: Програмата започва да се изпълнява от входния старт (код:0005), когато се изпълни операторът code:0013~0014, машинният код на оператора jmp short S1 на етикета S2 се копира в code:0008, а IP адресът е 0016. В този момент, ако няма инструкция jmp short s, програмата ще се изпълни в s2:jmp short s1, ще се прочете jmp short s1 в инструкционния буфер и IP=0022; а трансферът от s2 към s1 е вътрешносегментен трансфер, форматът на машинния код е EB disp, а disp=обозначение s1-обозначение s2=(00018-0022) допълнение=F6, така че машинният код на командата jmp short s1 трябва да е EBF6. Затова EBF6 се копира в единицата код:0008~код:0009. 2. Стъпка 2: Прочетете инструкциите jmp short s (EBF0) в инструкционния буфер, IP=IP+0002=0018; допълващият код на обозначението s-обозначение s0=(0008-0018) = F0, а прехвърлянето от s0 към s е трансферът в рамките на сегмента, а форматът на машинния код е EB disp (т.е. EBF0) 3. Стъпка 3: Командата jmp short s(EBF0) е команда за промяна на IP адреса след изпълнение на командата EBF0, IP=IP+(обозначение s-обозначение s0)=0008, сочеща към единицата код:0008. 4. Стъпка 4: Прочетете съдържанието на кода на единицата:0008. Тъй като командата jmp short s1 (EBF6) на s2 се копира в единицата код:0008~code:0009, след четене на съдържанието на устройството, IP=IP+0002=000A 5. Стъпка 5: Инструкция jmp short s1 (EBF6) е команда за промяна на IP след изпълнение на командата EBF6, IP=IP+(обозначение s1-обозначение s2)=0000, сочеща към единицата код:0000. 6. Стъпка 6: Програмата преминава в code:0000 за изпълнение, тоест нормалният край е завършен. 3. Постскриптум Правилно анализирайте този код: Трябва ли да разберете процеса на изпълнение на CPU инструкции и jmp short? (изчислено чрез модификация на интелектуалната собственост). Освен това, комплементният код на резултата от изчислението на офсета също е ключов. След като анализирах този на пръв поглед необичаен код, придобих по-дълбоко разбиране за инструкциите на JMP в асемблера.
|