Еще один вопрос по поводу вывода asm компилятора C - PullRequest
2 голосов
/ 15 августа 2010

очень быстрый вопрос для вас.Когда я сохраняю некоторую автоматическую переменную в C, вывод asm выглядит следующим образом: MOV ESP+4,#25h, и я просто хочу знать, почему компилятор не может вычислить этот ESP+4 адрес.

Я обдумал это и действительно не могу найти причину для этого.Я имею в виду, не знает ли компилятор о значении esp?Так должно быть.И при использовании другого объектного файла это также не должно быть проблемой, поскольку переменные могут быть просто представлены адресом и связаны позднее, когда все автоматические переменные известны, и, следовательно, можно назначить правильный адрес.Спасибо.

Ответы [ 5 ]

3 голосов
/ 15 августа 2010

Нет, он не может знать значение esp заранее.

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

Теперь, когда функция введена, точное значение esp будет зависеть от того, сколько разфункция вызывала себя ранее, и компилятор не мог знать об этом во время компиляции.Если вы сомневаетесь в этом, возьмите такую ​​функцию:

void foobar(int n)
{
    if (rand() % n != 17)
        foobar(n + 1);
}

Компилятор не сможет быть настолько умным, чтобы заранее определить, вызовет ли функция себя еще раз.

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

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


PS: Теперь что-то еще.На самом деле вам вообще не нужно оптимизировать [esp+N], потому что это не должно занимать больше процессорного времени, чем простое [esp] ... по крайней мере, на процессорах Intel Pentium.Можно сказать, что они уже содержат оптимизации именно для этого и даже более сложных сценариев.Если вам интересны процессоры Intel, я предлагаю вам поискать документацию для чего-то, что называется MOD R / M и SIB байт машинной инструкции, например, здесь для байта SIB или здесь или, конечно, в официальной документации Intel для разработчиков ЦП.

3 голосов
/ 15 августа 2010

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

2 голосов
/ 15 августа 2010

Нет, компилятор не знает значение заранее. В нескольких чрезвычайно простых программах (где есть только один возможный «маршрут» от main к любой другой вызываемой функции) это может , но я не знаю компилятора, который пытается вычислить это , Если у вас есть рекурсия или функция вызывается из более чем одного места, указатель стека будет иметь разные значения в зависимости от того, откуда он был вызван.

Нет особого смысла делать это в любом случае - так как указатель стека используется так интенсивно, большинство ЦП предназначены для того, чтобы сделать косвенную адресацию из указателя стека чрезвычайно эффективной. Фактически, это часто более эффективно, чем абсолютный адрес.

2 голосов
/ 15 августа 2010

Указатель стека не может быть рассчитан во время компиляции.Для простого примера, почему это невозможно, просто подумайте о рекурсивной функции: одна и та же переменная имеет разные адреса для каждого вызова, но всегда выполняется один и тот же код.

1 голос
/ 15 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...