Странные результаты в GDB - PullRequest
0 голосов
/ 09 февраля 2012

Я читаю книгу на языке C, в которой много говорится о asm, и смотрю на регистры и память в GDB.Проблема в том, что когда я компилирую и дизассемблирую один и тот же исходный код (фактически используя исходные файлы, поставляемые с компакт-диском книги), инструкции по сборке выглядят несколько иначе, чем в книге.В книге используется сборка со вкусом intel, и я помещаю "set disassembly intel" в gdb, так что это не так ... просто инструкции в другом порядке, некоторые все вместе разные, и есть несколько других причуд.

Например, в книге есть инструкция mov в регистре eip:

(gdb) x/i $eip
mov DWORD PTR[ebp-4], 0x0

, соответствующая инициализации переменной i в 0, в цикле for (i = 0, i <10, i ++) </p>

Однако в моей консоли gdb, с точкой останова в одном месте (установите break main; run), я вижу это:

(gdb) x/i $eip
mov DWORD PTR[esp+0x1c], 0x0

обратите внимание, что она ссылается на другой регистр все вместе -esp вместо ebp, если я проверяю значение esp, это 0x1c.Но если я попытаюсь проверить, что находится в 0x1c или в esp + 0x1c, это говорит мне, что я не могу смотреть на эти адреса

Так что, поскольку книга продолжается, я вообще не могу следовать,потому что он начинает следовать тому, что находится в ebp, ebp-4 и так далее, и в моем ассемблере, похоже, ничего не происходит с регистром ebp

Книга была написана в 2008 году, поэтомуЯ не могу представить, что это настолько устарело, что изменение версии gcc или gdb привело бы к значительному изменению (или сделал это?) ... возможно, есть какая-то оптимизация компилятора или что-то включено по умолчанию, чточто дает такие разные результаты?

Заранее спасибо

Редактировать: Странно.Я попробовал каждое из предложений, и ничего не получалось.Затем я выполнил команду rm a.out и перекомпилировал заново, и теперь она работает нормально (инструкции по-прежнему отличаются от той, что написана в книге, но я могу проверить адрес, соответствующий адресу книги; пока я могу следовать соответствующей схеме, все в порядке,не должно быть точно такой же asm, это просто сделало бы это слишком легким!) Еще раз спасибо за вашу помощь и предложения.

Ответы [ 3 ]

1 голос
/ 09 февраля 2012

Есть миллион вещей, которые могут вызвать это. Если бы вы скомпилировали свой код на другой архитектуре, я бы ожидал этого (и нет, это даже не обязательно означает 32 против 64 бит - буквально любая другая архитектура ЦП вообще может изменить порядок выполнения, как я объясню) , Если вы компилируете свои программы с оптимизацией, это изменит порядок выполнения, чтобы наилучшим образом использовать конвейер вашего ЦП. Это может означать добавление некоторых инструкций NOOP или их полное переупорядочение (в пределах разумного, конечно). Более того, некоторые процессоры имеют несколько способов выполнения действий, один из которых обычно быстрее, чем другой (на ум приходит инструкция Intel LOOP - современные компиляторы избегают этой инструкции, как чумы, потому что она ужасна). Если один регистр более эффективен, чем другой, он будет его использовать.

Мораль этой истории: в целях обучения как у автора, так и у читателя должны быть отключены все оптимизации. Также для добавленных бонусных баллов: используйте ту же версию gcc и ту же платформу.

1 голос
/ 09 февраля 2012

Похоже, что скомпилированный код был скомпилирован с -fomit-frame-pointers, который стал по умолчанию в GCC-4.6.

Попробуйте построить с явным -fno-omit-frame-pointer. Я ожидаю, что результаты будут выглядеть намного ближе к книге.

0 голосов
/ 09 февраля 2012

Все это будет зависеть от платформы и компилятора. Боюсь, вы ничего не можете сделать.

...