Книга: О.А.Калашников. Ассемблер Это Просто. Учимся программировать

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
background image

Часть II. Усложняем задачи 

62 

Этот  оператор  абсолютно  ничего  не  делает,  не  меняет  содержимое  регистров  

и флаги, но занимает 1 байт. Его обычно используют для резервирования места ли-
бо для того, чтобы "забить" ненужный код, когда исходник на ассемблере отсутст-
вует. Например, в случае, когда программа перед стартом проверяет версию опера-
ционной  системы,  а  версия,  которая  установлена  на  вашем  компьютере,  не 
соответствует  требуемой  программой.  Для  этого  данным  оператором  "забивают" 
участок кода, который проверяет версию ОС. Все это позволяет сделать редактор 
Hacker's View, который можно загрузить с сайта: http://www.Kalashnikoff.ru. 

Запомните  машинный  код  данной  команды: 

90h

.  Если  вы  в  любом  текстовом 

редакторе, который позволяет редактировать файлы в шестнадцатеричном формате 
(Volcov Commander, Hacker's View), вручную введете приведенные ниже строки, то 
получится коротенькая программа, которая абсолютно ничего не делает: 

90h 
90h 
0CDh 
20h 

6.2.2. Хитрая программа 

Рассмотрим одну очень интересную и хитрую программу (листинг 6.5). Ни на од-

ном другом языке программирования нельзя создать подобную (\006\prog06.asm). 

Листинг 6.5. Программа для практики 

(01) CSEG segment 
(02) assume cs:CSEG, es:CSEG, ds:CSEG, ss:CSEG 
(03) org 100h 
 
(04) Begin: 
(05)        mov sp,offset Lab_1 

(06)        mov ax,9090h 
(07)        push ax 
(08)        int 20h 
 
(09) Lab_1: 
(10)        mov ah,9 
(11)        mov dx,offset Mess 
(12)        int 21h 
 
(13)        int 20h 
 
(14) Mess db 'А все-таки она выводится! $' 
 
(15) CSEG ends 
(16) end Begin 

background image

Глава 6. Работа со стеком 

63 

То, что вы видите — "обман зрения". На первый взгляд, программа что-то дела-

ет  с  регистром 

sp

,  а  затем  завершает  работу.  Строки  (09)—(12)  вообще  не  будут 

работать. Но это глубокое заблуждение! Попробуйте запустить ее под отладчиком. 
Вы увидите, что CodeView, TurboDebuger, AFD будут выдавать какой-то "мусор": 
непонятные операторы, сообщения типа "программа завершилась", хотя до коман-
ды 

int 20h

 дело не дошло (рис. 6.7). Но если запустить ее просто из DOS, то стро-

ка появится на экране, т. е. программа будет работать корректно, при этом выводя 
строку на экран (рис. 6.8)! Данный пример — типичный случай "заламывания рук" 
многим отладчикам. И вы уже можете это делать! 

Почему так происходит? Ответ один: указанные выше отладчики используют стек 

пользовательской программы (т. е. той программы, которая работает под отладчиком). 

Ваша задача — разобрать "по полочкам" программу. 

 

Что происходит? 

 

Почему строка выводится? 

 

Почему отладчик работает неверно? 
Вопросов море. И вам необходимо дать ответ на них. Разобравшись с програм-

мой  самостоятельно,  вы  почувствуете  силу  и  неограниченные  возможности  ас-
семблера. Не бойтесь экспериментировать! Компьютер будет часто зависать, но это 
не главное! Ваши мучения приведут вас к пониманию работы процессора! 

Рис. 6.7. Некорректная работа отладчика с нашей программой 

Рис. 6.8. Корректная работа нашей программы без отладчика 

background image

Глава 7 

Операторы сравнения 

7.1. Разбор программы из главы 6 

В  начале  данной  главы  рассмотрим  прошлую  программу.  Итак,  в  листинге 7.1 

показано решение. 

Листинг 7.1. Программа из главы 6 

... 

(01)    mov sp,offset Lab_1 
(02)    mov ax,9090h 

(03)    push ax 
(04)    int 20h 
 
(05) Lab_1: 
(06)    mov ah,9 
(07)    mov dx,offset Mess 
(08)    int 21h 
(09)    int 20h 
... 

Что же все-таки происходит? 
Как мы узнали из главы 6, команда 

nop

 имеет машинный код 

90h

. Посмотрите на 

строку  (02).  В  ней  мы  загружаем  в  регистр 

ax

  два  числа 

90h

  (или  два  оператора 

nop

). В 

sp

 заносим адрес метки 

Lab_1

 (01). Теперь  стек находится внутри нашей 

программы,  а,  точнее,  вершина  стека  на  метке 

Lab_1

.  Стоит  отметить,  что  сама 

метка памяти не занимает! Она нужна только для MASM/TASM, которые, дойдя до 
строки (05), запомнят адрес (смещение) метки в программе (что равно 

109h

). 

После выполнения строки (01) посмотрите в отладчике, какое число находится в 

sp

, 

а также на код, который расположен по этому адресу. Вы увидите, что по адресу 

109h

находится команда 

mov ah,09

, т. е. физически метки 

Lab_1

 в памяти не существует. 

Теперь внимание! В строке (03) мы "толкаем" в стек два числа 

90h

, т. е. две ко-

манды 

nop

. Что происходит дальше? Стек, как вы уже знаете, "растет" снизу вверх. 

background image

Глава 7. Операторы сравнения 

65 

После помещения в стек числа 

sp

 не увеличивается, а уменьшается, что отображе-

но стрелкой на рис. 7.1. Команда 

int 20h

 занимает 2 байта. Это можно наблюдать 

в отладчике или в Hacker's View. Машинный код 

int 20h

 равен 

0CDh, 20h

. Теперь 

вы знаете, как "вручную" набрать простейшую COM-программу в редакторе. Если 
есть  редактор,  позволяющий  смотреть  шестнадцатеричные  числа  (например, 
Volcov Commander), то введите в создаваемом файле 

CD

 и 

20

. Сохраните файл как 

COM (например, prog.com). Его размер должен быть 2 байта. Можете смело запус-
кать получившийся COM-файл. 

Рис. 7.1. Программа в отладчике AFD Pro 

Итак, 

int  20h

 занимает 2 байта. Командой 

push ax

 (03) мы заносим в стек два 

числа 

90h

, которые процессор воспримет как два оператора 

nop

.  Так как смещение 

в регистре 

sp

 указывает на 

int 20h

, то эта команда будет затерта двумя оператора-

ми 

nop

. Все! Вместо 

int 20h

 (завершение работы программы) процессор выполнит 

два оператора 

nop

, которые ничего не делают! После этого выведет строку на эк-

ран. На рис. 7.1 показан результат работы этой программы в отладчике. 

Обратите внимание, как легко можно менять код собственной программы в ас-

семблере буквально "на лету". 

Эта простая программа наглядно демонстрирует работу стека. 
Теперь рассмотрим, почему отладчики CodeView, AFD, Turbo Debugger работа-

ют  некорректно.  Внимательно  прочтите  следующую  фразу:  вышеперечисленные 
отладчики используют стек нашей программы. Говоря простым языком, отладчик, 
загрузив к себе в память нашу программу, использует тот же стек (те же регистры 

ss:sp

), что и наша программа. Отладчику ведь тоже надо хранить где-то свои дан-

ные.  Например,  после  выполнения  одной  команды  нашей  программы,  запомнить 
адрес следующей. Одно дело на экране, но другое — в стеке отладчика, который по 
сути  является  нашим!  Поэтому, переместив стек в область кода написанной нами 

background image

Часть II. Усложняем задачи 

66 

программы, мы тем самым переносим и стек отладчика, который, в свою очередь, 
сохраняет  в  нем  свои  данные.  Но  мы  знаем,  что  заносить  в  стек  можно  не  более 
двух байтов, иначе стек будет переполнен, т. к. мы очень уж мало места отвели под 
стек. Проблема отладчика в том, что он об этом "не знает", да и заносит в стек до-
вольно много информации, которая попросту затирает нашу программу. 

7.2. Оператор сравнения 

В предыдущих главах мы рассматривали функцию 

10h

 прерывания 

16h

, которая 

ждет  от  пользователя  нажатия  клавиши.  Теперь  настало  время  научиться  прове-
рять, какую же именно клавишу нажал пользователь. 

Вышеуказанная функция возвращает код нажатой клавиши в регистр 

ax

. Как же 

нам ее проверить? Для этого рассмотрим новый оператор сравнения 

cmp

 (табл. 7.1  

и листинг 7.2). 

Таблица 7.1. Оператор сравнения 

cmp

Команда 

Перевод 

Назначение 

Процессор 

cmp приемник, источник 

Compare 

— сравнить 

Сравнение 

8086 

Листинг 7.2. Пример использования оператора cmp 

... 
(01)    mov ah,10h 
(02)    int 16h 
(03)    cmp al,'Y' 
(04)    jz Yes_key 
... 
(05) Yes_key: 
... 

На строке (02) компьютер остановится и будет ждать до тех пор, пока пользова-

тель не нажмет какую-нибудь клавишу. После этого прерывание 

10h

 поместит в 

ax

код клавиши, и выполнение программы продолжится. В строке (03) мы проверяем, 
нажата ли клавиша <Y>. Обратите внимание на запись: 

cmp al,'Y' 

Нам  не  обязательно  знать  ASCII-код  клавиши.  Вместо  этого  в  одинарных  ка-

вычках  просто  указываем  саму  клавишу.  При  ассемблировании  программы 
MASM/TASM  автоматически  заменит  ее  соответствующим кодом. Если вы запус-
тите программу под отладчиком, то увидите, что код будет не 

cmp al,'Y' 

а 

cmp al,59h 

Источник: https://files.student-it.ru/previewfile/2839