Как называется программа отладчик ассемблера
Перейти к содержимому

Как называется программа отладчик ассемблера

  • автор:

Turbo Assembler

Часто бывает так, что программа, успешно пройдя этапы трансляции и компоновки, все же работает не так, как ожидалось или вообще не работает. Это значит, что формально, с точки зрения правил языка программирования, программа написана правильно (в ней нет синтаксических ошибок), однако алгоритм ее в чем-то неверен. Для отладки такой программы следует воспользоваться услугами интерактивного отладчика. Интерактивным он называется потому, что вся работа с ним осуществляется в непрерывном диалоге с пользователем.

Познакомимся с отладчиком TD.EXE из пакета TASM, воспользовавшись программой из первого примера.

Как уже отмечалось, для полного использования возможностей отладчика следует при трансляции программы указать в числе других ключ /zi, а при компоновке — ключ /v:

tasm /z/zi/n p,p,p tlink /v p,p

Кроме того, следует убедиться, что в вашем рабочем каталоге имеется и загрузочный (Р.ЕХЕ) и исходный (P.ASM) файл, поскольку отладчик в своей работе использует оба этих файла. Вызовем отладчик командой

td p

На экране появится кадр отладчика, в котором видны два окна — окно Module с исходным текстом отлаживаемой программы и окно Watches для наблюдения за ходом изменения заданных переменных в процессе выполнения программы (см.рис.).

Окно Watches нам не понадобится, и его можно убрать, щелкнув мышью по маленькому квадратику в левом верхнем углу окна или введя команду Alt+F3, предварительно сделав это окно активным. Переключение (по кругу) между окнами осуществляется клавишей F6.

Верхняя строка кадра отладчика представляет собой главное меню. Для перехода в меню необходимо нажать клавишу Alt и первую (выделенную цветом) букву требуемого пункта. Для выбора затем конкретного действия надо с помощью клавиш со стрелками вверх и вниз- выделить нужный пункт и нажать клавишу Enter.

В нижней строке отладчика приведены его основные команды, вызов которых осуществляется нажатием на функциональные клавиши F1. F10. В действительности команд гораздо больше; некоторые из них можно реализовать только с помощью пунктов главного меню, другие вызываются комбинациями функциональных и управляющих (Alt, Ctrl или Shift) клавиш.

Рассмотрим типичные действия, к которым приходится прибегать по ходу отладки программы.

После вызова отладчика и загрузки в память отлаживаемой программы ее первое предложение помечается значком сплошного треугольника ; там же устанавливается и значок подчеркивания _, который играет в отладчике роль курсора. По мере выполнения программных предложений значок сплошной треугольник будет перемещаться по тексту программы, всегда указывая на очередное (еще не выполненное) предложение; значок _ можно перемещать с помощью клавиш со стрелками.

Нажав одну из клавиш F8 или F7, мы выполним одно предложение программы. Различие этих команд весьма существенно: команда F7 (trace, трассировка) позволяет войти внутрь вызываемых подпрограмм, а также выполнять циклы шаг за шагом. Команда F8 (step, шаг), наоборот, выполняет подпрограммы и циклы как одно неразрывное действие, что заметно ускоряет пошаговую отладку программы, если мы, например, уверены, что вызываемая подпрограмма выполняется правильно.

Можно выполнить сразу и целый фрагмент программы, т. е. несколько предложений. Для этого надо поместить курсор _ перед тем предложением, на котором требуется сделать остановку (или на любой символ внутри него), и нажать клавишу F4 (here, сюда). Выполнятся все строки программы до той, на которой установлен курсор; значок сплошной треугольник переместится на эту строку. Далее можно опять выполнять программу построчно, нажимая на клавишу F8, или, установив в требуемом месте курсор, выполнить следующий фрагмент, нажав F4.

Для повторного выполнения программы ее следует «рестартовать». Для этого надо выбрать в главном меню пункт Run-Program reset или просто нажать Ctrl+F2.

Важнейшим элементом отладки программы является наблюдение значений тех или иных полей данных, особенно тех, которые заполняются программой динамически, т. е. по ходу ее выполнения. Для того чтобы вывести на экран содержимое поля данных, надо поместить курсор на имя этого поля (например, mesg в нашем примере) и выбрать пункт меню Data-Inspect. В появившемся окне ввода переменной (см.рис.) можно скорректировать имя интересующего нас поля данных или ввести новое; если имя правильное, достаточно нажать клавишу Enter.

В кадр отладчика будет выведено окно с характеристиками и содержимым указанной переменной (см.рис.). Отладчик сообщает, что переменная mesg хранится в памяти по адресу 5D82:000, т. е. имеет сегментный адрес 5D82h и смещение OOOOh, и описана как последовательность из 12 байт. Тут же приводятся значения всех байтов нашей строки, включая их начертание на экране, а также десятичное и 16-ричное представление.

В окне Inspecting можно изменить значение отображаемого поля данных. Для этого надо, сделав это окно активным и поместив курсор на отображение конкретного элемента нашего символьного массива, например элемента с индексом 12 (знак «!»), ввести команду Alt+F10. Эта команда для любого активного окна открывает его внутреннее меню с дополнительными возможностями. В данном случае внутреннее меню будет иметь вид, показанный на нижнем рисунке.

Нас будет интересовать пункт Change (изменение). Выбрав этот пункт, мы получим окно, в котором можно ввести требуемое значение изменяемого данного. На следующем рисунке показано это окно с введенным символом ‘>’, которым будет заменен восклицательный знак. Можно было вместо символа в одинарных кавычках ввести его 16-ричный код ASCII, если он известен (число ЗЕ для знака >). Допустим ввод и десятичного кода, если завершить его буквой d F2d).

Если теперь, не выходя из отладчика, выполнить программу до конца, на экран вместо ! будет выведен >.

Для того чтобы, находясь в отладчике, увидеть результат работы программы, надо ввести команду Alt+F5 (или выбрать пункт Window-User screen главного меню). Возврат в кадр отладчика осуществляется нажатием любой клавиши.

Необходимо отдавать себе отчет в том, что любые изменения, вносимые в текст программы в процессе работы с отладчиком, будут действовать только до конца данного сеанса (даже, точнее говоря, до рестарта программы). Отладчик изменяет не файл Р.ЕХЕ, хранящийся на диске, а только его копию в памяти. После завершения сеанса работы с отладчиком все, что было загружено в память, исчезает вместе с внесенными нами изменениями.

Начальное окно отладчика дает недостаточно информации для серьезной работы с программой. При отладке программы на уровне языка ассемблера необходимо контролировать все регистры процессора, включая регистр флагов, а также во многих случаях поля данных вне программы (например, векторы прерываний или системные таблицы). Для этого надо командой Alt+V, С (пункт главного меню View-CPU) открыть «окно процессора» (см.рис.).

Окно процессора состоит, в свою очередь, из пяти внутренних окон для наблюдения текста программы на языке ассемблера и в машинных кодах, регистров процессора, флагов, стека и содержимого памяти. С помощью этих окон можно полностью контролировать работу процессора при выполнении отлаживаемой программы. Для того чтобы можно было работать с конкретным окном, надо сделать его активным, щелкнув по нему мышью. Переходить из окна в окно можно также (по кругу), нажимая клавишу Tab. Для управления ходом программы используются функциональные клавиши, перечисленные в нижней строке кадра (F7 или F8 для пошагового выполнения, F4 для выполнения до курсора и т. д.). Курсор во всех внутренних окнах окна процессора выглядит в виде синей ленточки. Добавим еще, что, щелкнув мышью по значку стрелки вверх в правом верхнем углу окна процессора, можно увеличить это окно до размеров кадра отладчика.

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

Выполните программу до первой команды int 21h (предложение 7) и просмотрите содержимое регистров процессора. Вы увидите, что в старшей половине регистра АХ находится число 09h — номер вызываемой функции DOS. Младшая половина регистра АХ заполнена «мусором» — остатком от выполнения последней операции с регистром АХ. В регистре DX будет OOOOh — относительный адрес первого байта строки mesg в сегменте команд. Изменим этот относительный адрес. Для этого надо перейти в окно регистров, поместить курсор на строку, отображающую содержимое регистра DX, и ввести команду Alt+F10, открывающую внутреннее меню окна регистров (см.рис.).

Как видно из рисунка, меню окна регистров предоставляет возможность выполнить увеличение содержимого регистра на 1 (Increment), уменьшить его на 1 (Decrement), обнулить (Zero) и заменить на любое заданное значение (Change). Выбрав пункт Change, занесем в регистр DX число 5 (см.рис.).

Теперь, если выполнить очередную команду (int 21h), DOS выведет на экран строку, начало которой расположено в байте 5 сегмента данных. В нашей фразе «Hello, world!» байт 5 приходится на запятую (нумерация байтов в строке, естественно, начинается с нуля). В результате на экран будет выведена строка

Еще одной полезной операцией является вывод содержимого области памяти, начиная с заданного адреса (дамп памяти). Таким образом можно изучать не только поля данных программы, но и содержимое вообще любых участков памяти компьютера, в частности системных таблиц. Посмотрим, например, как выглядит в памяти блок окружения программы.

Любая программа, загруженная в память, состоит из двух отдельных блоков: собственно программы и ее окружения, которое располагается обычно перед программой, хотя не обязательно вплотную к ней.

Окружение представляет собой область памяти, в которой в виде символьных строк записаны значения переменных, называемых переменными окружения, например

PROMPT= $p$g PATH=C:\DOS; C:\TOOLS; C:\NC;

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

Пользователь может включить в окружение строки определения дополнительных переменных с помощью команды SET. Часто в качестве значений таких переменных указываются пути к каталогам со вспомогательными файлами или ключи, задающие режим работы различных программ.

Учебники. Программирование для начинающих.

курсы повышения квалификации Мы используем Куки. Это позволяет нам анализировать взаимодействие посетителей с сайтом и делать его лучше. Продолжая пользоваться сайтом, вы соглашаетесь с использованием файлов Cookie.

Programm.ws — это сайт, на котором вы можете почитать литературу по языкам программирования , а так-же посмотреть примеры работающих программ на С++, ассемблере, паскале и много другого..

Программирование — в обычном понимании, это процесс создания компьютерных программ.
В узком смысле (так называемое кодирование) под программированием понимается написание инструкций — программ — на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). Соответственно, люди, которые этим занимаются, называются программистами (на профессиональном жаргоне — кодерами), а те, кто разрабатывает алгоритмы — алгоритмистами, специалистами предметной области, математиками.
В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения ЭВМ. Более точен современный термин — «программная инженерия» (также иначе «инженерия ПО»). Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение.

Assembler

Глава 2. Основы программирования

Подготовка и отладка программы

Процесс подготовки и отладки программы на языке ассемблера включает этапы подготовки исходного текста, трансляции, компоновки и отладки.
Подготовка исходного текста программы выполняется с помощью любого текстового редактора, хотя бы редактора, встроенного в программу Norton Commander, или еще более удобного редактора Norton Editor. При использовании одного из более совершенных текстовых процессоров, вроде Microsoft Word, следует иметь в виду, что эти программы добавляют в выходной файл служебную информацию о формате (размер страниц, тип шрифта и др.), которая будет непонятна транслятору. Однако практически все текстовые редакторы и процессоры позволяют вывести в выходной файл «чистый текст», без каких-либо служебных символов. Именно таким режимом и надлежит воспользоваться в нашем случае.
В принципе для подготовки исходного текста можно воспользоваться любым редактором системы Windows, например, программой WordPad или Блокнотом. Однако в этом случае возникнут неприятности с русским шрифтом. Как известно, корпорация Microsoft приняла для своих русифицированных продуктов собственную кодировку русских символов, расходящуюся со стандартной, используемой в приложениях DOS. Если программу, использующую русский текст в качестве комментариев, или выводящую его на экран, подготовить в одном из редакторов Windows, то при ее просмотре и запуске в среде DOS вместо русского текста вы увидите бессмысленный набор символов. Поэтому программы, предназначенные для выполнения под управлением MS-DOS, лучше и подготавливать в среде DOS. Файл с исходным текстом должен иметь расширение .ASM.
Следующая операция состоит в трансляции исходного текста программы, т.е. в преобразовании строк исходного языка в коды машинных команд. Эта операция выполняется с помощью транслятора с языка ассемблера (т.е. с помощью программы ассемблера). Известные разработчики программного обеспечения — корпорации IBM, Borland, Microsoft и др. предлагают свои варианты трансляторов, несколько различающиеся своими возможностями и системой обозначений. Однако входной язык любого транслятора, включающий в себя мнемонику машинных команд и других операторов и правила написания предложений ассемблера, для всех ассемблеров одинаков, поэтому при подготовке и отладке примеров данной книги можно с равным успехом воспользоваться любой из указанных программ. Мы, как уже отмечалось, использовали программы пакета TASM 5.0 (фирменные названия этих программ — Turbo Assembler,
Turbo Link и Turbo Debugger, а имена соответствующих им файлов — TASM.EXE, TLINK.EXE и TD.EXE).
После трансляции образуются два файла — листинг трансляции и объектный файл с расширением OBJ. Листинг представляет собой текстовый файл, предназначенный для чтения в каком-либо редакторе, и содержит исходный текст оттранслированной программы вместе с машинными кодами команд. В случае обнаружения транслятором каких-либо ошибок, в листинг также включаются сообщения об этих ошибках.
Рассмотрим элементы листинга трансляции примера 1-1 из предыдущей главы. На рис. 2.1 приведен несколько сокращенный текст этого листинга, из которого удалены комментарии к отдельным предложениям.
айту. В этом случае следует использовать перетаскивание в обратном направлении. А именно, разыщите целевой файл, например, при помощи программы Проводник, затем перетащите его значок на карту узла — на изображение родительского документа.

Рис. 2.1. Листинг трансляции программы 1-1.

Рассматривая листинг, можно отметить ряд полезных моментов общего характера. Предложения программы с операторами assume, segment, ends, end, как уже отмечалось ранее, не транслируются в какие-либо машинные коды и не находят отражения в памяти. Они нужны лишь для передачи транслятору служебной информации о способе трансляции команд (assume), границах сегментов (segment и end) и строке, на которой следует завершить обработку исходного текста (end).
Каждому транслируемому предложению программы соответствует определенное смещение, причем задание смещений выполняется в каждом сегменте в отдельности. Первая команда mov AX,data имеет смещение от начала сегмента команд, равное нулю. Она занимает 3 байта, поэтому следующая команда начинается с байта 3 и имеет соответствующее смещение.
Транслятор не смог полностью определить код команды mov AX,data. В этой команде в регистр АХ засылается сегментный адрес сегмента data. Однако этот адрес станет известен лишь в процессе загрузки выполнимого файла программы в память. Поэтому в листинге на месте этого адреса стоят нули, помеченные буквой s, напоминающей о том, что здесь должен быть пока неизвестный сегментный адрес.
Еще одна помеченная команда с кодом ВА 0000 располагается в строке 8 листинга. В этой команде в регистр DX заносится смещение поля с именем msg, расположенное в сегменте данных (ключевое слово offset, указанное перед именем поля, говорит о том, что речь идет не о содержимом ячейки msg, а об ее смещении). Поле msg расположено в самом начале сегмента данных, и его смещение от начала сегмента равно 0, что и указано в коде команды. Почему же эта команда помечена буквой т, являющейся сокращением слова relocatable, переместимый?
Чтобы ответить на этот вопрос, нам придется рассмотреть, как сегменты программы размещаются в памяти. Как уже говорилось, любой сегмент может располагаться в памяти только с адреса, кратного 16, т.е. на границе 16-байтового блока памяти (параграфа). Конкретный адрес программы в памяти зависит от конфигурации компьютера, — какой размер занимает DOS, сколько загружено резидентных программ и драйверов, а также в каком режиме запускается программа — в отладчике или без него. Предположим, что сегментный адрес сегмента команд оказался равным 1306п (рис. 2.2, а). В нашей программе сегмент команд имеет размер 11h байт (что указано в строке 13 листинга), т.е. занимает целый параграф плюс один байт. Сегмент данных имеет размер 14h байт (строка 19 листинга) и тоже требует для своего размещения немного больше одного парафафа. Из-за того, что сегмент данных должен начаться на границе параграфа, ему будет назначен сегментный адрес 1308h и между сегментами образуется пустой промежуток размером 15 байт.
Потеря 15 байт из многомегабайтовой памяти, разумеется, не имеет никакого значения, однако в некоторых случаях, например, при компоновке единой профаммы из большого количества модулей с небольшими по размеру подпрофаммами, суммарная потеря памяти может оказаться значительной.

Рис. 2.2. Расположение сегментов программы в памяти при выравнивании по умолчанию (а) и на байт (б).

Для того, чтобы устранить потери памяти, можно сегмент данных объявить с выравниванием на байт:

Такое объявление даст возможность системе загрузить сегмент данных так, как показано на рис. 2.2, б. Сегмент данных частично перекрывает сегмент команд, начинаясь на границе его последнего параграфа (в нашем случае по адресу 1307h). Для того, чтобы данные не наложились на последние команды сегмента команд, они смещаются вниз так, что начинаются сразу же за сегментом команд. В нашем примере, где сегмент команд «выступает» за сегментный адрес 1307h всего на 1 байт, данные и надо сместить на этот 1 байт. В результате поле msg, с которого начинается сегмент данных, и которое в листинге имело смещение 0, получит смещение 1. Все остальные адреса в сегменте данных также сместятся на один байт вперед. В результате данные будут располагаться в физической памяти вплотную за командами, без всяких промежутков, однако все обращения в сегменте команд к данным должны быть скорректированы на величину перекрытия сегментов, в нашем случае — на 1 байт. Эта коррекция выполняется системой после загрузки программы в память, но еще до ее запуска. Адреса, которые могут потребовать описанной коррекции, и помечаются в листинге трансляции буквой «г». Из сказанного следует очень важный и несколько неожиданный вывод: коды команд программы в памяти могут не совпадать с кодами, показанными в листинге трансляции. Это обстоятельство необходимо учитывать при отладке программ с помощью интерактивного отладчика, который, естественно, показывает в точности то, что находится в памяти, и что не всегда соответствует листингу трансляции.
Вернемся к рассмотрению листинга трансляции. Данные, введенные нами в программу, также оттранслировались: вместо символов текста в загрузочный файл попадут коды ASCII этих символов. Так, буква «П» преобразовалась в код 8Fh, буква «р» в код ЕО и т. д. При выводе этих кодов на экран видеосистема компьютера преобразует их назад в изображения символов, записанных в исходном тексте программы.
Из листинга трансляции легко определить размер отдельных составляющих программы. В нашем случае длина сегмента команд составляет 11h = 17 байт, длина сегмента данных — 14h = 20 байт, а под стек отведено ровно столько, сколько мы запросили в программе — 100h = 256 байт. Размер же всей программы окажется больше суммы длин сегментов, во-первых, из-за пустых промежутков между сегментами (у нас на них уйдет 15 + 12 = 27 байт), и, во-вторых, за счет подсоединения к программе обязательного префикса программы, имеющего всегда размер 256 байт.
Как мы уже отмечали, в результате трансляции программы образуется два файла — с листингом и с объектным модулем программы.
Объектный файл является основным результатом работы транслятора и представляет собой текст программы, преобразованный в машинные коды. Хотя в этом файле уже присутствуют коды команд, он не может быть выполнен. Для того чтобы получить выполнимую программу, объектный файл необходимо скомпоновать.
Компоновка объектного файла выполняется с помощью программы компоновщика (редактора связей). Эта программа получила такое название потому, что ее основное назначение — подсоединение к файлу с основной программой файлов с подпрограммами и настройка связей между ними. Однако компоновать необходимо даже простейшие программы, не содержащие подпрограмм. Дело в том, что у компоновщика имеется и вторая функция — изменение формата объектного файла и преобразование его в выполнимый файл, который может быть загружен в оперативную память и выполнен. Файл с программой компоновщика обычно имеет имя LINK.EXE, хотя это может быть и не так. Например, компоновщик пакета TASM назван TLINK.EXE. В результате компоновки образуется загрузочный, или выполнимый файл с расширением .ЕХЕ.
Отладку и изучение работы готовой программы удобнее всего осуществлять с помощью интерактивного отладчика, который позволяет выполнять отлаживаемую программу по шагам или с точками останова, выводить на экран содержимое регистров и областей памяти, модифицировать (в известных пределах) загруженную в память программу, принудительно изменять содержимое регистров и выполнять другие действия, позволяющие в наглядной и удобной форме контролировать выполнение программы.
Рассмотрим вкратце основные приемы работы с «турбоотладчиком» TD.EXE из пакета TASM. Приступая к работе с отладчиком, следует убедиться, что в рабочем каталоге имеются и загрузочный (Р.ЕХЕ), и исходный (P.ASM) файлы, так как отладчик в своей работе использует оба эти файла. Для запуска отладчика следует ввести команду

На экране появится кадр отладчика, в котором видны два окна — окно Module с исходным текстом отлаживаемой программы и окно Watches для наблюдения за ходом изменения заданных переменных в процессе выполнения программы (рис. 2.3). Окно Watches нам не понадобится, и его можно убрать, щелкнув мышью по маленькому квадратику в левом верхнем углу окна, или введя команду + , предварительно сделав это окно активным. Переключение (по кругу) между окнами осуществляется клавишей .

Рис. 2.З. Начальный кадр отладчика с текстом отлаживаемой программы.

В процессе отладки программы на экран приходится выводить много дополнительных окон; они перекрываются и часто скрывают друг друга. Чтобы увидеть их все одновременно, размер окон приходится уменьшать, а сами окна перемещать по экрану. Режим изменения размеров и положения окна включается командой + , после чего клавиши со стрелками перемещают окно по экрану, а те же клавиши при нажатой клавише позволяют изменять его размер. Выход из режима настройки окна осуществляется нажатием клавиши .
Начальное окно отладчика дает слишком мало информации для отладки программы. В нем можно выполнять программу по частям до местоположения курсора (клавиша ) и команда за командой (клавиша ); можно также с помощью окна Watches наблюдать изменения заданных полей данных. Однако для отладки программы на уровне языка ассемблера необходимо контролировать все регистры процессора, включая регистр флагов, а также, во многих случаях, поля данных вне программы (например, векторы прерываний или системные таблицы). Гораздо более информативным является «окно процессора», которое вызывается с помощью пункта Vicw>CPU верхнего меню или командой + + (рис. 2.4).

Рис. 2.4. Окно процессора с внутренними окнами.

Окно процессора состоит, в свою очередь, из 5 внутренних окон для наблюдения текста программы на языке ассемблера и в машинных кодах, регистров процессора, флагов, стека и содержимого памяти. С помощью этих окон можно полностью контролировать ход выполнения отлаживаемой программы. Для того чтобы можно было работать с конкретным окном, например, прокручивать его содержимое, надо сделать его активным, щелкнув по нему мышью. Перейти из окна в окно можно также с помощью клавиатуры, нажимая клавишу Tab. Посмотрим, какие сведения можно извлечь из содержимого окна процессора.
Содержимое сегментных регистров DS и ES одинаково и составляет HF5h. Эта значит, что программа загружена в память, начиная с физического адреса 11F50, т.е. приблизительно с 70-го килобайта. Чем заняты первые 70 Кбайт памяти? Обычно компьютер конфигурируется так, что в обычной памяти размещается только малая часть DOS (около 16 Кбайт), драйверы обслуживания расширенной памяти и резидентная часть COMMAND.COM. Основная часть DOS, остальные драйверы и необходимые резидентные программы (например, русификатор) переносятся в расширенную память. В этом случае системные области в начале памяти занимают всего 20 — 25 Кбайт. Тем не менее наша программа начинается не с 25-го, а с 70-го килобайта. Произошло это из-за того, что программа запущена под управлением отладчика, который сначала загружается в память сам, и лишь затем загружает отлаживаемую программу. Но отсюда следует, что если бы мы запустили программу без отладчика, она попала бы на другое место в памяти, гораздо ближе к ее началу. В большинстве случаев это обстоятельство не имеет особого значения, так как любая программа должна одинаково успешно выполняться в любом месте памяти, однако необходимо отдавать себе отчет, что отладчик изменяет операционную среду программы (в частности, переносит ее на другое место в памяти). Строго говоря, программа под управлением отладчика выполняется не совсем так, как она выполнялась бы непосредственно в DOS.
Еще один пример «самодеятельности» отладчика можно увидеть в том же окне регистров процессора. Содержимое всех регистров общего назначения (АХ, ВХ, СХ, DX, SI, DI и ВР) равно 0. Отсюда можно сделать вывод, что DOS, загружая программу в память, очищает регистры процессора. Однако на самом деле это совсем не так! Регистры очищает не DOS, а отладчик. При обычном запуске программы исходное содержимое регистров практически непредсказуемо, и ни в коем случае нельзя рассчитывать, что в них будут нули. Иногда можно столкнуться и с более тонким влиянием отладчика на ход выполнения программы, вплоть до того, что некоторые виды программ, например, управляющие подключенной к компьютеру аппаратурой, в отладчике будут выполняться просто неверно.
Итак, после загрузки программы в память содержимое регистров DS и ES оказалось одинаковым. Это вполне естественно, если вспомнить, что перед выполнением оба регистра указывают на префикс программы (см, рис. 1.9). Вслед за префиксом располагается сегмент команд и поскольку префикс всегда занимает точно lOOh байт (т.е. 10h параграфов по 16 байт), то содержимое CS в нашем случае должно быть равно HF5h + 10h = 1205h. Так оно и есть (см. рис. 2.4).
В нашем примере программа должна начать выполняться с метки begin, поскольку именно эту метку мы указали в качестве операнда завершающей директивы end. Эта метка относится к самой первой команде сегмента команд и ее значение (или, что то же самое, смещение первой команды программы) должно быть равно 0. Поэтому исходное значение указателя команд, как это видно из рис. 2.4, тоже равно 0. В дальнейшем, по мере выполнения команд, значение IP будет возрастать. Выполним две первые команды программы, дважды нажав клавишу . Состояние программы после этой операции показано на рис. 2.5.

Рис. 2.5. Состояние программы после выполнения двух первых команд.

Видно, что указатель команд получил значение 5 и показывает на очередную (еще не выполнявшуюся) команду mov AH,09h, относительный адрес которой равен 5. Сегментный регистр DS получил значение 1207h, что должно соответствовать сегментному адресу сегмента данных. Вспомним, что сегмент команд у нас занимает 11h байт и требует в памяти 2 параграфа. Сегмент команд имеет сегментный адрес 1205h, следовательно, сегментный адрес сегмента данных должен быть равен 1207h, что мы и получили.
Обратим внимание на самую правую колонку в окне процессора, в которой индицируются состояния флагов процессора. Как уже говорилось, состояния флагов заново устанавливаются процессором после выполнения каждой команды, и по ним можно в определенной степени судить о результате команды. С самого начала у нас был установлен только флаг IF (i в окне отладчика), что свидетельствует о включенном механизме аппаратных прерываний; остальные флаги сброшены. После выполнения двух первых команд состояние регистра флагов не изменилось. Произошло это потому, что команда пересылки mov не изменяет состояния флагов. Поскольку в нашей программе нет никаких команд, кроме mov и hit, а команда hit тоже состояния флагов обычно не изменяет, то наблюдать с помощью нашего примера функционирование регистра флагов не удастся.
Рассмотрим теперь стек. Сегмент данных имеет у нас размер 14h байт, и под него в памяти надлежит выделить 2 параграфа. Это объясняет содержимое сегментного регистра стека SS — 1209п. Под стек отведено 256 байт, поэтому исходное положение SP (под дном стека) соответствует смещению l00h.
Наконец, стоит еще обратить внимание на нижнюю половину окна команд, заполненную странными командами add [bx+si],al. Таких команд, да еще в таком количестве, в нашей программе нет, их «придумал» отладчик, пытаясь деассемблировать промежуток между сегментом команд и сегментом данных, заполненный нулями. Код 0000h соответствует команде add [bx+si],al, которую и изобразил отладчик.
Таким образом, рассмотрев информацию, предоставленную отладчиком, мы подтвердили все предыдущие рассуждения о расположении в памяти сегментов программы и об инициализации регистров процессора при загрузке программы в память.
Обратимся теперь к окну дампа. При запуске отладчика в окно дампа выводится содержимое памяти, начиная с адреса DS:0000h, т.е. начало префикса программы (см. рис. 2.4 и 2.5). Для того, чтобы вывести на экран что-либо иное, надо воспользоваться командой + , которая для каждого внутреннего окна процессора открывает дополнительное меню. Вид этого меню зависит от того, какое окне было активным в момент ввода команды. На рис. 2.6 показано дополнительное меню окна дампа.

Рис. 2.6. Дополнительное меню окна дампа памяти.

Чаще всего приходится пользоваться первым пунктом этого меню Goto, с помощью которого можно задать любой адрес (входящий или не входящий в сегменты программы), и получить дамп этого участка.. На рис. 2.7. изображено содержимое окна дампа после ввода начального адреса в виде DS:0 (тот же результат даст начальный адрес DS:msg, а так же и просто msg, так как по умолчанию сегментный адрес берется из DS). Как и следовало ожидать, по этому адресу расположено наше единственное данное — строка текста, выводимая программой на экран. Кстати, в окне дампа видно начало промежутка между сегментами (данных и стека), заполненного нулями.

Рис. 2.7. Дамп сегмента данных.

Assembler. Установка интерпретатора и запуск первой программы через DOSBox

В данной статье разбирается способ установки интерпретатора и запуск файла EXE через DOSBox. Планировалось погрузить читателя в особенности программирования на TASM, но я согласился с комментаторами. Есть много учебников по Ассемблер и нет смысла перепечатывать эти знания вновь. Лично мне в изучении очень помог сайт av-assembler.ru. Рекомендую. В комментариях также вы найдёте много другой литературы по Assembler. А теперь перейдём к основной теме статьи.

Для начала давайте установим наш старенький интерпретатор.
Ссылка

Почему именно vk.com?

Я прекрасно понимаю, что это ещё тот колхоз делиться файлами через обсуждения VK, но кто знает, во что может превратиться эта маленькая группа в будущем.

После распаковки файлов, советую сохранить их в папке Asm на диск C, чтобы иметь меньше расхождений с представленным тут материалом. Если вы разместите директорию в другое место, изменится лишь путь до файлов, когда вы будете использовать команду mount.

Для запуска интерпретатора нам так же потребуется эмулятор DOSBox. Он и оживит все наши компоненты. Скачаем и установим его!
Ссылка

В папке Asm я специально оставил файл code.asm. Именно на нём мы и потренируемся запускать нашу программу. Советую сохранить его копию, ибо там хранится весь код, который в 99% случаев будет присутствовать в каждом вашем проекте.

s_s segment s_s ends d_s segment d_s ends c_s segment assume ss:s_s, ds:d_s, cs:c_s begin: mov ax, d_s mov ds, ax mov ax, 0 ; Your code needs to be here mov ah, 4ch int 21h c_s ends end begin

Итак. Запускаем наш DOSBox и видим следующее:

Для простоты сопоставим имя пути, по которому лежит наша папка Asm. Чтобы это сделать, пропишем следующую команду:

mount d: c:\asm

Здесь вместо d: мы можем использовать любую другую букву. Например назвать i или s. А C это наш реальный диск. Мы прописываем путь до наших файлов ассемблера.

Теперь, откроем смонтированный диск:

Прописав команду dir, мы сможем увидеть все файлы, которые там хранятся. Здесь можно заметить и наш файл CODE с расширением ASM, а также дату его создания.

И только теперь мы начинаем запускать наш файл! Бедные программисты 20 века, как они только терпели всё это? Пропишем следующую команду:

tasm code.asm

После мы увидим следующее сообщение, а наша директория пополнится новым файлом с расширением OBJ.

Теперь пропишем ещё одну команду:

tlink code.obj

В нашей папке появилась ещё пара файлов – CODE.MAP и CODE.EXE. Последний как раз и есть исполняемый файл нашего кода assembler.

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

td code

Этот старинный интерфейс насквозь пропитан духом ушедшей эпохи старых операционных систем. Тем не менее…

Нажав F7 или fn + F7 вы сможете совершить 1 шаг по коду. Синяя строка начнёт движение вниз, изменяя значения регистров и флагов. Пока это всего лишь шаблон, на котором мы потренировались запускать нашу программу в режиме дебага. Реальное “волшебство” мы увидим лишь с полноценным кодом на asm.

Небольшой пример для запуска

Прога проверяет, было ли передано верное число открывающих и закрывающих скобок:

s_s segment dw 20 dup('$') s_s ends d_s segment string db '()','$'; result db 0 d_s ends c_s segment assume ss:s_s,ds:d_s,cs:c_s begin: ; начало программы mov ax,d_s mov ds,ax xor ax,ax lea si, string ;Ищем в строке скобку search: lodsb ;Проверка, это конец строки? cmp al, '$' je endString ;Это открывающая или закрывающая скобка? ;Это открывающие скобки? cmp al, '(' je inStack cmp al, '' je outStack cmp al, ']' je outStack jmp search ;Помещаем скобку в Stack, увеличиваем счётчик inStack: inc cx push ax jmp search ;Выниманием из Stack скобку, проверяем пару outStack: ;Была передана лишняя закрыв. скобка? cmp cx, 0 je error3 dec cx pop bx ;Вскрытая скобка закрыта верно? cmp bl, '(' jne close1 cmp al, ')' jne error1 jmp search close1: cmp bl, '[' jne close2 cmp al, ']' jne error1 jmp search close2: cmp bl, '' jne error1 jmp search ;Остались ли незакрытые скобки? endString: cmp cx, 0 jne error2 jmp exit ;Скобки остались, это ошибка №2 error2: mov result, 2 jmp exit ;Лишняя скобка передана, ошибка №3 error3: mov result, 3 jmp exit ;Закрывающая скобка несоответствует открывающей, ош №1 error1: mov result, 1 jmp exit ;Пред-завершение. Каков результат программы? exit: cmp result, 1 jne enough ;Ищем нужную скобку для исправления ошибки №1 cmp bl, '(' jne next1 mov bl, ')' jmp enough next1: cmp bl, '' jmp enough next2: cmp bl, '[' mov bl, ']' jmp enough enough: mov dl, result xor dx, dx mov dl, bl mov ah,4ch int 21h c_s ends end begin

Давайте ознакомимся с имеющимися разделами.

CS

Code segment – место, где turbo debug отражает все найденные строки кода. Важное замечание – все данные отражаются в TD в виде 16-ричной системы. А значит какая-нибудь ‘12’ это на самом деле 18, а реальное 12 это ‘C’. CS аналогичен разделу “Begin end.” на Pascal или функции main.

DS

Data segment, отражает данные, которые TD обнаружил в d_s. Справа мы видим их символьную (char) интерпретацию. В будущем мы сможем увидеть здесь наш “Hello, world”, интерпретируемый компилятором в числа, по таблице ASCII. Хорошей аналогией DS является раздел VAR, как в Pascal. Для простоты можно сказать, что это одно и тоже.

SS

Stack segment – место хранения данных нашего стека.

Регистры

Все эти ax, bx, cx, si, di, ss, cs и т. д. – это наши регистры, которые используются как переменные для хранения данных. Да, это очень грубое упрощение. Переменные из Pascal и регистры Assembler это не одно и тоже, но надеюсь, такая аналогия даёт более чёткую картину. Здесь мы сможем хранить данные о циклах, арифметических операциях, системных прерываниях и т. д.

Флаги

Все эти c, z, s, o, p и т.д. это и есть наши флаги. В них хранится промежуточная информация о том, например, было ли полученное число чётным, произошло ранее переполнение или нет. Они могут хранить результат побитого сдвига. По опыту, могу сказать, на них обращаешь внимание лишь при отладке программы, а не во время штатного исполнения.

Ещё одно замечание. Если вы измените данные исходного файла с расширением .ASM, то вам придётся совершить все ранее описанные операции вновь, ибо обновив например code.asm вы не меняете code.obj или code.exe.

Маленькая шпаргалка для заметок:

  1. mount d: c:\asm – создаём виртуальный диск, где корень –папка asm
  2. d: — открываем созданный диск
  3. tasm code.asm – компилируем исходный код
  4. tlink code.obj – создаём исполняемый файл
  5. td code – запускаем debug
  6. F7 – делаем шаг в программе

Буду ждать комментарии от всех, кому интересен Assembler. Чувствую, я где-то мог накосячить в терминологии или обозначении того или иного элемента. Но статья на Habr отличный повод всё повторить.

Что такое x64dbg и как им пользоваться?

Введение и обзор применения x64dbg в качестве инструмента для анализа вредоносных программ. x64dbg — отладчик с открытым исходным кодом для Windows, который часто используется в качестве инструмента анализа вредоносных программ. Отладчик предназначен для пошагового выполнения кода, что позволяет отслеживать его действия. Отладчики необходимы для поиска и устранения ошибок, однако они также позволяют декомпилировать вредоносные программы.

Этой публикацией мы открываем серию из четырех статей о x64dbg.

  • Часть 1. Что такое x64dbg и как им пользоваться?
  • Часть 2. Распаковка вредоносного ПО с помощью x64dbg
  • Часть 3. Обзор Stack Memory
  • Часть 4. Анализ вредоносного ПО с помощью x64dbg

Обзор x64dbg

В отличие от программиста, у которого при отладке есть доступ к собственному исходному коду, аналитики вредоносных программ обычно сталкиваются с компилированным кодом на языке ассемблера (например, с файлом Windows .exe или .dll ). Ассемблер — низкоуровневый язык программирования, предназначенный для определенной архитектуры компьютера, такой как 64-разрядная архитектура (отсюда название x64dbg). Существуют также отладчики для 32-разрядной архитектуры, известные под названием x32dbg. Аналитик вредоносной программы редко начинает работу с использования отладчика. Сначала он выполняет статический анализ и может даже запустить вредоносное ПО на виртуальной машине с помощью ряда инструментов для анализа на поведенческом уровне, чтобы попытаться понять, что делает вредоносное ПО. После этого запускается отладчик для распаковки вредоносного ПО и последующего анализа его конкретных функций — так называемого декомпилирования.

Как установить x64dbg

Это не потребует особых усилий. Его можно загрузить со страницы загрузки на официальном сайте https://x64dbg.com/.

  • Примечание. Не пытайтесь анализировать вредоносное ПО без предварительной настройки безопасной виртуализированной среды. x64dbg не следует устанавливать на вашем хост-компьютере для анализа вредоносных программ.

Следует загружать последнюю версию x64dbg, которая расположена в разделе загрузок на сайте x64dbg и имеет формат ZIP-архива. Содержимое можно извлечь в любую папку по выбору, а для запуска программного обеспечения достаточно открыть отдельные двоичные файлы. Установка не предполагает выполнения каких-либо шагов. Как упоминалось ранее, программа представлена в двух версиях: одна для 64-разрядных двоичных кодов, а вторая — для 32-разрядных. Существует также еще одна версия — x96 (64 + 32). С ее помощью пользователь может просто перетаскивать вредоносное ПО на значок программы, и после проверки архитектуры будет загружаться соответствующая версия отладчика.

Для чего предназначено каждое окно?

При открытии вредоносной программы в x64dbg отладчик поначалу может казаться довольно сложной и запутанной программой. В отладчике имеется шесть основных областей: пять окон и главная панель инструментов, о них мы расскажем ниже.

Главная панель инструментов X64dbg

В самой верхней части окна отображается имя анализируемого файла 267.exe, идентификатор процесса, который был выделен операционной системой, а также анализируемый в настоящее время модуль (о необходимости использования модуля будет рассказано в следующей статье). Значки на панели инструментов — ключ для изучения ассемблерного кода вредоносного ПО. Основные значки для лучшего понимания начинающими пользователями показаны на рисунке ниже.

Значки довольно просты и понятны:

  • Значок папки: открыть файл для анализа;
  • Круговая стрелка: вернуться к началу программы;
  • Значок «стоп»: остановить программу, если она запущена в x64dbg;
  • Значок стрелки: запустить программу;
  • Значок паузы: приостановить выполнение программы.

Чаще всего аналитик вредоносного ПО использует последние два. Один из них представлен в виде стрелки, указывающей вниз и имеющей небольшой кружок под ней. Эта кнопка называется Step Into («Шаг с заходом»), а следующий значок — кнопка Step Over («Шаг с обходом»). Вредоносное ПО состоит из множества функций, которые написаны или импортированы его разработчиком. Для анализа конкретной функции аналитику необходимо выполнить «Шаг с заходом» в функцию, чтобы просмотреть ее ассемблерный код. В противном случае, если функция не представляет интереса, нажимается кнопка «Шаг с обходом». Об этих функциях будет подробно рассказано в следующей статье. В строке со вкладками внизу изображения содержатся различные области просмотра и данные, которые упрощают анализ.

Ниже описаны наиболее важные вкладки:

  • CPU («ЦП»): отображает ассемблерный код сверху вниз.

  • Graph («График»): графическое представление, которое позволяет пользователю наглядно посмотреть, какая функция вызывается другой. Они похожи на другие инструменты, такие как IDAPro и Ghidra.

  • Breakpoints («Контрольные точки»): позволяет выполнить поиск инструкций или строк, представляющих интерес, и задать контрольные точки для этих инструкций. Затем x64dbg позволяет пользователю выполнять программу до тех пор, пока она не достигнет контрольной точки, с целью ее дальнейшего анализа. На изображении ниже показаны некоторые контрольные точки, которые заданы в функциях Windows CreateDirectoryW и WriteFile.

  • Memory Map («Карта распределения памяти»): показывает, какие данные хранятся в памяти, а также путь к ним. В приведенном ниже примере раздел анализируемой вредоносной программы .text расположен по адресу 00F21000. Столбец Protection («Защита») также показывает, является ли эта область памяти исполняемой, читаемой или доступной для записи. На эту информацию указывают флажки E, R и W. Эти данные пригодятся чуть позже, когда мы покажем, как использовать карту распределения памяти для распаковки вредоносного ПО.

  • Call Stack («Стек вызовов»): полезная функция после установки контрольной точки на определенной функции Windows. На предыдущем изображении контрольная точка была установлена на CreateDirectoryW, поэтому при каждом создании вредоносным ПО каталога на скомпрометированном устройстве срабатывает эта контрольная точка, и x64dbg останавливается на данной функции. Используя стек вызовов, можно увидеть, какой код, написанный автором вредоносного ПО, называется CreateDirectoryW, и определить место создания этого каталога и способ его вызова.

Главное окно X64dbg

В главном окне x64dbg находится содержимое выбранной вкладки; по умолчанию этой вкладкой является вкладка CPU («ЦП»), содержащая ассемблерные инструкции. Первый столбец содержит EIP (указатель команд). Он просто указывает на следующий запускаемый фрагмент кода. Во втором столбце показаны адреса с инструкциями в пределах двоичного кода, поэтому в приведенном выше примере EIP указывает на адрес 0138CD97. Третий столбец представляет собой шестнадцатеричное представление инструкций в столбце 4. Столбец 4 — месторасположение ассемблерных инструкций. Опять же, в приведенном выше примере показан EIP, указывающий на следующую инструкцию, которую нужно запустить, а именно push ebp. Пятый столбец содержит данные, заполненные x64dbg, или заметки, добавленные аналитиком. В приведенном выше примере видно, что 0138CD97 — это «точка входа» вредоносного ПО, то есть начало кода его разработчика и место начала основной функции. Третий столбец с ассемблерными инструкциями — вероятно, наиболее важный, поскольку именно эти данные используются аналитиком вредоносного ПО при определении назначения программы. Ниже приведено несколько наиболее распространенных инструкций:

  • PUSH: поместить значение в стек
  • POP: вывести значение из стека
  • CALL: выполнить функцию
  • RET: вернуть значение выполненной функции
  • JMP: перейти по адресу
  • CMP: сравнить два значения
  • MOV: переместить данные из одного места в другое.
  • ADD: прибавить значение
  • SUB: вычесть значение
Окно x64dbg с информацией о регистрах

Следующее окно содержит информацию о регистрах. Регистры используются программой для хранения данных, к которым можно обращаться для последующего использования, и некоторые из них предназначены для вполне конкретных целей.

  • EAX: сложить, умножить и вернуть значения
  • EBX: общий регистр, используемый для различных операций
  • ECX: используется в качестве счетчика
  • EDX: общий регистр, используемый для различных операций
  • EBP: ссылка на аргументы и локальные переменные
  • ESP: указывает на последний аргумент в стеке
  • ESI / EDI: используется в инструкциях по переносу памяти

EIP — не регистр, а указатель инструкции, указывающий на текущую инструкцию в x64dbg. В этом поле указан адрес расположения инструкции.

Окно x64dbg с информацией о стековой памяти

В третьем окне отображаются параметры, которые перенесены в стек. Подробнее об этом окне будет написано в следующей статье, рассказывающей о том, как работает stack memory.

Окно x64dbg со стеком и данными

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

Окно x64dbg с данными дампа

Шестое и последнее окно содержит данные дампа. Окна «дампа» позволяют пользователю видеть, какие данные хранятся в регистре или какие данные расположены по определенному адресу.

Надеемся, что эта статья дала вам представление о том, что такое x64dbg и как перемещаться по инструменту. В следующих нескольких статьях будет описана методика, используемая для декомпилирования вредоносных программ, стековая память и способы ее использования отладчиком x64dbg. Кроме того, будут приведены примеры некоторых вредоносных программ и продемонстрировано несколько навыков декомпилирования.

  • Блог компании Varonis Systems
  • Информационная безопасность
  • Assembler

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *