Я помню, как однажды пытался отладить программу на Macintosh (около 1991 г.), где сгенерированный код очистки компилятором для стекового кадра между 32K и 64K был ошибочным, поскольку он использовал добавление 16-битного адреса, а не 32-битного (16-разрядное количество, добавленное в регистр адресов, будет расширено на 68000). Последовательность была что-то вроде:
copy stack pointer to some register
push some other registers on stack
subtract about 40960 from stack pointer
do some stuff which leaves saved stack-pointer register alone
add -8192 (signed interpretation of 0xA000) to stack pointer
pop registers
reload stack pointer from that other register
Чистым эффектом было то, что все было в порядке , за исключением , что сохраненные регистры были повреждены, и один из них содержал константу (адрес глобального массива). Если компилятор оптимизирует переменную в регистр во время раздела кода, он сообщает об этом в файле информации отладки, чтобы отладчик мог правильно вывести его. Когда константа так оптимизирована, компилятор, по-видимому, не включает такую информацию, поскольку в этом не должно быть необходимости. Я отследил все, выполнив «printf» из адреса массива, и установил точки останова, чтобы я мог просматривать адрес до и после printf. Отладчик правильно сообщил адрес до и после printf, но printf вывел неправильное значение, поэтому я разобрал код и увидел, что printf помещает регистр A3 в стек; просмотр регистра A3 до того, как printf показал, что он имеет значение, весьма отличное от адреса массива (printf показал значение, которое фактически содержало A3).
Я не знаю, как я мог бы отследить это, если бы не смог использовать и отладчик, и printf вместе (или, если на то пошло, если бы я не понимал 68000 ассемблерный код).