Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29210
Скачиваний: 1689
Часть 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
Глава 6. Работа со стеком
63
То, что вы видите — "обман зрения". На первый взгляд, программа что-то дела-
ет с регистром
sp
, а затем завершает работу. Строки (09)—(12) вообще не будут
работать. Но это глубокое заблуждение! Попробуйте запустить ее под отладчиком.
Вы увидите, что CodeView, TurboDebuger, AFD будут выдавать какой-то "мусор":
непонятные операторы, сообщения типа "программа завершилась", хотя до коман-
ды
int 20h
дело не дошло (рис. 6.7). Но если запустить ее просто из DOS, то стро-
ка появится на экране, т. е. программа будет работать корректно, при этом выводя
строку на экран (рис. 6.8)! Данный пример — типичный случай "заламывания рук"
многим отладчикам. И вы уже можете это делать!
Почему так происходит? Ответ один: указанные выше отладчики используют стек
пользовательской программы (т. е. той программы, которая работает под отладчиком).
Ваша задача — разобрать "по полочкам" программу.
Что происходит?
Почему строка выводится?
Почему отладчик работает неверно?
Вопросов море. И вам необходимо дать ответ на них. Разобравшись с програм-
мой самостоятельно, вы почувствуете силу и неограниченные возможности ас-
семблера. Не бойтесь экспериментировать! Компьютер будет часто зависать, но это
не главное! Ваши мучения приведут вас к пониманию работы процессора!
Рис. 6.7. Некорректная работа отладчика с нашей программой
Рис. 6.8. Корректная работа нашей программы без отладчика
Глава 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
. Что происходит дальше? Стек, как вы уже знаете, "растет" снизу вверх.
Глава 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
), что и наша программа. Отладчику ведь тоже надо хранить где-то свои дан-
ные. Например, после выполнения одной команды нашей программы, запомнить
адрес следующей. Одно дело на экране, но другое — в стеке отладчика, который по
сути является нашим! Поэтому, переместив стек в область кода написанной нами
Часть 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