|
Коли я натрапив на наступний код під час вивчення асемблерної мови, я просто подумав, що програма не може закінчитися нормально. Однак після відстеження однокрокового відстеження було виявлено, що програма може закінчуватися нормально, і сталося дивне явище: коли програма починала виконувати код:0005 на code:0014, вона продовжувала стрибати до code:0008 за допомогою команди jmp. Однак при продовженні виконання кроку вперед програма одразу переходить у code:0 замість code:0018 (тобто сегмент S1). Спочатку я не розумів, що відбувається, але після багатьох однокрокових спостережень все одно почувався дивно. Після ретельного вивчення використання інструкцій JMP у підручнику [1], а потім аналізу програми у поєднанні з машинним кодом, я отримав нове розуміння інструкцій JMP. Інструкції для машини збірки коду (IP Address Offset) Припустимо CS:код (одиниця: h) Сегмент коду mov ax, 4c00h 0000 B8004C int 21h 0003 CD21 start: mov ax,0 0005 B80000 S: NoP 0008 90 NOP 0009 90 mov di, зсув 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 int 21h 001B CD21 mov ax, 0 001D B80000 s2: JMP короткий сезон 1 0020 EBF6 NOP 0022 90 Код закінчується кінець початку 1. Наступні два моменти потрібно чітко зрозуміти 1. Процес виконання інструкцій процесора виглядає так: <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) complement=F6, тому машинний код команди jmp short s1 має бути EBF6. Отже, EBF6 копіюється у одиницю code:0008~code:0009. 2. Крок 2: Зчитайте короткі записи інструкції jmp 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. Післямова Правильно проаналізуйте цей код: потрібно зрозуміти процес виконання інструкцій процесора та jmp short? (розрахований шляхом модифікації IP). Крім того, додатковий код результату обчислення зсуву також є ключем. Після аналізу цього, здавалося б, аномального коду, я отримав глибше розуміння інструкцій JMP у асемблері.
|