Debug — Программа-отладчик, которую используют для проверки и отладки выполняемых файлов. Использовалась при операционной системе MS-DOS. Под более поздние версии операционных систем работает через эмулятор MS-DOS и имеет ограниченные возможности.
Данная программа является консольным приложением и предназначена для создания или изменения кода файлов. С помощью неё можно создавать простые приложение под MS-DOS и отслеживать их работу. Данный отладчик находится на самом низком уровне компиляторов assembler. Но обладает неплохими возможностями такими как просмотр, изменение памяти и получение состояния регистров.
Откройте окно командной строки, введите команду debug и нажмите клавишу [Enter]. В результате будет запущен отладчик debug в интерактивном режиме. Дефис и мигающий курсор означают, что отладчик ждет ввода команды. Одна из наиболее полезных возможностей отладчика состоит в том, что с его помощью вы можете вводить небольшие фрагменты кода на ассемблере и проверять их работу. Проиллюстрируем эти возможности на простом примере. Введите букву a (на латинице) и нажмите клавишу [Enter]. Эта команда переводит отладчик в режим ввода команд ассемблера. Каждая команда ассемблера записывается в одну строку и заканчивается нажатием клавиши [Enter]. Чтобы закончить ввод ассемблерных команд следует на новой пустой строке еще раз нажать клавишу [Enter]. Введите три строчки кода, представленного на рисунке.
Поясним что делает эта программа. Первая строка кода помещает число 2 в регистр ax. Ассемблерная команда mov (от английского move - перемещать) копирует содержимое второго операнда в первый операнд. Вторая строка кода аналогичным образом помещает число 3 в регистр bx. И, наконец, третья строчка кода, использующая команду add складывает содержимое регистров ax и bx и помещает результирующую сумму в регистр ax.
Отладчик позволяет достаточно просто и эффективно понаблюдать за работой программы. Введите букву r и нажмите клавишу [Enter]. В результате появится информация о содержимом регистров процессора. Поскольку в нашей программе используются только регистры ax и bx сосредоточим свое внимание на их содержимом. Поскольку программа еще не запускалась на исполнение, видим, что содержимое регистров равно нулю. Чтобы понять как работает программа удобно использовать пошаговый режим отладки, когда на каждом шагу выполняется одна строчка программы. Чтобы выполнить один шаг нужно ввести букву t и нажать клавишу [Enter]. Видим, что в результате выполнения первой строки программы содержимое регистра ax стало равным 2. Аналогичным образом можно выполнить оставшиеся две строчки и пронаблюдать за результатом их исполнения.
Для более полного понимания работы микропроцессора рекомендуется обратить внимание на содержимое других регистров, а также на третью строку выводимой информации.
Регистр IP (Instruction Pointer - указатель команды) всегда содержит адрес следующей выполняемой команды. Обратите внимание что в самом начале содержимое данного регистра равно 100 и указывает на адрес первой команды, т.к. вся программа располагается в памяти, начиная именно с этого адреса. Кстати, адреса вводимых команд указываются слева в тех строках где эти команды вводятся. Эти адреса представляются в виде двух чисел разделенных двоеточием. Первое число определяет так называемый сегментный адрес, а второе число смещение адреса от начала сегмента. Заметьте, что на каждом следующем шаге отладки значение регистра IP увеличивается таким образом, чтобы указывать на следующую команду программы. Заметьте также, что третья выводимая строка содержит информацию о следующей выполняемой команде. Эта информация включает в себя машинный адрес данной команды, саму команду на машинном языке, т.е. в виде шестнадцатеричного числа, и ассемблерное представление команды. Необходимо также обратить внимание, что содержимое всех сегментных регистров DS, ES, SS и CS равно сегментному адресу программы.
Рекомендуется рассмотреть аналогичным образом ряд других команд ассемблера. Это позволит не только узнать как применяются ассемблерные команды, но и освоить работу с отладчиком.
Команда сложения ADD имеет следующий формат
и может складывать как 8-, так и 16-битовые операнды.
Команда ADD складывает содержимое операнда-источника и операнда-приемника и помещает результат в операнд-приемник. Ее действие можно описать как
приемник = приемник + источник
Команда ADD может воздействовать на шесть флагов:
Флаг переноса CF равен 1, если результат сложения не помещается в операнде-приемнике; в противном случае он равен нулю.
Флаг четности PF равен 1, если результат имеет четное число битов со значением 1; в противном случае он равен нулю.
Вспомогательный флаг переноса AF равен 1, если результат сложения десятичных чисел требует коррекции; в противном случае он равен нулю.
Флаг нуля ZF равен 1, если результат равен 0; в противном случае он равен нулю.
Флаг знака SF равен 1, если результат отрицателен (старший бит равен 1) ; в противном случае он равен нулю.
Флаг переполнения OF равен 1, если сложение двух чисел одного знака (оба положительные или оба отрицательные) приводит к результату, который превышает диапазон допустимых значений приемника в обратном коде, а сам приемник при этом меняет знак. В противном случае он равен нулю.
Флаги SF и OF имеют смысл только при сложении чисел со знаком,
а флаг AF – только при сложении десятичных чисел.
Команда
добавляет 1 к содержимому регистра или ячейки памяти,
но в отличие от команды ADD не воздействует на флаг переноса CF.
Команда вычитания SUB имеет следующий формат
Команда SUB вычитает операнд-источник из операнда-приемника и возвращает результат в операнд-приемник, т. е.
приемник = приемник – источник
Команда SUB может воздействовать на шесть флагов:
Флаг переноса CF равен 1, если требуется заем; в противном случае он равен нулю.
Флаг четности PF равен 1, если результат имеет четное число битов со значением 1; в противном случае он равен нулю.
Вспомогательный флаг переноса AF равен 1, если результат вычитания десятичных чисел требует коррекции; в противном случае он равен нулю.
Флаг нуля ZF равен 1, если результат равен 0; в противном случае он равен нулю.
Флаг знака SF равен 1, если результат отрицателен (старший бит равен 1) ; в противном случае он равен нулю.
Флаг переполнения OF равен 1, если при вычитании чисел имеющих разные знаки, результат превышает диапазон допустимых значений приемника в обратном коде, а сам приемник при этом меняет знак. В противном случае он равен нулю.
Флаги SF и OF имеют смысл только при вычитании чисел со знаком,
а флаг AF – только при вычитании десятичных чисел.
Команда
вычитает 1 из содержимого регистра или ячейки памяти, но при этом
(в отличие от команды SUB) не воздействует на флаг переноса CF.
Команда
вычитает значение операнда-приемника из нулевого значения и
тем самым формирует его дополнение до двух. Команда NEG оказывает
на флаги то же действие, что и команда SUB.
Команда
вычитает операнд-источник из операнда-приемника и в зависимости
от результата устанавливает или обнуляет флаги.
Но в отличие от команды SUB команда CMP не сохраняет результат вычитания.
Таким образом команда CMP не изменяет операнды.
Она целиком предназначена для установки значений флагов,
на основании которых команды условного перехода будут принимать решение о передаче управления.
Команда
умножает числа без знака и может умножать как байты, так и слова.
Источник это регистр общего назначения или ячейка памяти размером в байт или слово. В качестве второго операнда команда MUL использует содержимое регистра AL (при операциях над байтами ) или регистра AX (при операциях над словами ). Произведение имеет двойной размер и возвращается следующим образом:
Умножение байтов возвращает 16-битовое произведение в регистрах AH ( старший байт ) и AL (младший байт ).
Умножение слов возвращает 32-битовое произведение в регистрах DX ( старшее слово ) и AX (младшее слово ).
По завершении исполнения этих команд флаги переноса CF и переполнения OF показывают, какая часть произведения существенна для последующих операций. После исполнения команды MUL флаги CF и OF равны 0, если старшая половина произведения равна 0; в противном случае оба этих флага равны 1.
Команда MUL не позволяет в качестве операнда использовать непосредственное значение.
Такое значение перед умножением надо загрузить в регистр или в ячейку памяти.
Команда
выполняет деление чисел без знака.
Источник это делитель размером в байт или слово, находящийся в регистре общего назначения или в ячейке памяти.
Делимое должно иметь двойной размер; оно извлекается из регистров AH и AL ( при делении на 8-битовое число ) или из регистров DX и AX ( при делении на 16-битовое число ). Результаты возвращаются следующим образом:
Если операнд-источник представляет собой байт, то частное возвращается в регистре AL, а остаток в регистре AH.
Если операнд-источник представляет собой слово, то частное возвращается в регистре AX, а остаток в регистре DX.
Команда оставляет состояние флагов неопределенным, но если частное не помещается в регистре-приемнике ( AL или AX ), то процессор генерирует прерывание типа 0 ( деление на 0 ).