Типичные ошибки

 

 

Каждая программа имеет свои ошибки. Некоторые ошибки являются общими для всех программ. Одни характерны для программирования на ассемблере, другие не зависят от языка. К таким ошибкам относятся:

1. Отсутствие операций присвоения начальных значений переменным, в частности счетчикам или указателям адреса. Не следует думать, что перед началом выполнения программы значения регистров, признаков и ячеек памяти будут равны нулю.

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

3. Отсутствие в программе блоков обработки таких тривиальных ситуаций, как массивы или таблицы, не содержащие ни одного элемента или содержащие единственный элемент.

4. Инвертирование логических условий, например переход по нулю вместо перехода по не нулю. Не забывайте, что признак НУЛЬ равен 1 при нулевом результате и 0 в противном случае.

5. Неверный порядок операндов, например пересылка из А и В, хотя имелась в виду пересылка из В в А. В Intel 8080 по команде MOV А,В содержимое В посылается в А.

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

7. Отсутствие в логике программы блоков обработки таких необычных ситуаций, как отсутствие в таблице искомого элемента или проверка логического условия, которое никогда не выполняется. Подобные ошибки обычно приводят к зацикливанию.

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

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

10. Неверный переход в случае «равно». Например, переход по условию «число неотрицательно» вместо условия «число положительно»

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

А = В В = А

содержимое А и В станет равным содержимому В, так как первое присвоение стирает прежнее значение А. Правильный результат дает следующая последовательность операций

Т - А

А = В В = Т

12. Непонимание различия между числовыми и символьными данными. Изображения нуля в кодах ASCII или EBCDIC не совпадает с числом нуль. Большинство периферийных устройств используют для представления данных свои коды.

13. Непонимание различия между числами и кодированными представлениями чисел. Так, двоично-десятичный код 61 не совпадает с двоичным представлением числа 61.

14. Неправильное задание длины таблицы или блока. В ячейках 40—48 содержатся девять информационных слов вместо восьми.

15. Неправильное указание порядка операндов в некоммутативных операциях. Так, ассехмблерная команда SUB С вычитает содержимое регистра С из содержимого аккумулятора, а не наоборот. Программист должен быть особенно внимательным при использовании операций вычитания, сравнения и деления.

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

17. Игнорирование возможности возникновения переполнения при использовании операций над числами со знаком. Сложение чисел 64 и 64 в 8-битном процессоре дает —128 (проверьте сами!), а. сложение —128 и —128 дает 0.

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

Существует много других ошибок, однако приведенный перечень дает программисту представление о том, на что следует обратить внимание. Типичным примером решения задач отладки является следующая попытка написать на языке ассемблера Intel 8080 программу определения длины строки символов в коде ASCII, которая заканчивается символом «возврат каретки» (ВК) (ODla в коде ASCII). На рис. 6.13 показана первоначальная версия программы.

MBUF EQU 40H

CR EQU 00001101В

LXI H, MBUF ; Адресный указатель = начало

INX H ; строки

CHKCR: INR В ; Счетчик символов = счетчик символов

; +1

СМР М ; Счетчик символов = 0

JNZ CHKCR ; Следующий символ есть В К?

HLT
Рис. 6.13. Первоначальный вариант программы определения длины строка

Пример. Отладка программы, которая определяет длину строки.

Была выполнена простая процедура ручной отладки для случая, когда строка символов состояла из одного символа ВК, расположенного в ячейке MBUF. Прежде чем проанализировать данные, в начальном адресе по команде INX Н к указателю была добавлена единица.

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

Ручная проверка этой программы показала, что вместо команды JNZ DONE следует поставить команду JZ DONE, если процесс поиска следует закончить в тот. момент, когда анализируемый символ есть ВК. В простейшем случае, как и ожидается, результатом будет нулевая длина, указаннаяд р£ги<;тре .В.

Однако попытка применить программу к анализу строки, состоящей из символа, «пробел», за, которым следует символ ВК, также дает результат 0; следовательно, программа неверна. Ручная проверка выполнения цикла показала, что команда JNR В увеличивает содержимое счетчика, но затем следует передача управления на команду MVI В,0, которая вновь обнуляет этот счетчик. Метка CHKCR стоя ла в неверном месте. Исправленная программа показана на рис. 6.15.

 

   

MBUF
EQU
40H
 
CR
EQU
00001101В
 
 
LXI
H, MBUF
; Адресный указатель = начало строки
 
MVI
A, CR
; Загрузить символ ВК для выполне- ; ния, сравнений
СНКО?:
MVI
B,0
; Счетчик символов = 0
 
CMP
M
; Следующий символ есть ВК?
 
JNZ
DON В
; Да, идти к DONE
 
INX
H
 
 
INR
В i
; Нет, увеличить содержимое счетчика ; символов на 1
 
JMP
CHKCR
9
DONE:
HLT
 
 
MBUF
CR
EQU
EQU
LXI
40H
00001101B H, MBUF
 
MVI
A, CR
CHKCR:
MVI
CMP
JZ
INX
INR
B, 0 M
DONE
H
6
DONE:
JMP
HLT
CHKCR

 

 Рнс. 6.15. Окончательный вариант программы определения длины строки
Эта программа дала верный результат при анализе нес кольки-х контрольных строк символов. Приведенный пример показывает» что про* стая процедура ручной отладки при анализе логики программы, может оказаться не менее полезной, чем самые изощренные отладочные средства. Однако отладка систем реального времени гораздо сложнее, требует более серьезной подготовки и дополнительного оборудования.