Win32ASM Консольный ввод, томограф IDA и скальпель SoftICE



    d8ef8794     

Задача 3.


Есть ещё один регистр, ассоциируемый со стеком - ebp/bp, и описывается его функция так, что выговорить страшно – указатель базы кадра стека. Такое название этого регистра я нашел в книжке Юрова & Хорошенко "ASSEMBLER, учебный курс". Нет, конечно же, можно назвать калоши "мокроступами", а bitmap "двоично-точечной картинкой", но... "У меня нет слов, у меня есть только выражения в адрес того, кто заворачивает такие коленца" (C) Аркадий Белоусов. А по сему давайте заменим словосочетание "кадр стека" простым народным :) словом "фрейм", а "указатель базы" заменим на просто "база" (или "указатель" - по вкусу).

  В результате подобных терминологических "подстановок" получается следующая картина: есть у нас в компьютере некие "фреймы", располагаются они в стеке и адреса этих пока что непонятных нам штук завязаны с регистром ebp/bp.

  "Дело в следующем". Любая процедура/функция в терминах любого процедурного языка имеет (может иметь) нуль и больше параметров и локальных переменных. Область памяти, создаваемая (выделяемая) при вызове процедур для аргументов и локальных переменных, и называется фреймом. А чтобы процедура могла быть рекусивной (т.е. могла вызывать саму себя или вызываться из других процедур, которые она вызывает) или реентерабельной (т.е. чтобы код процедуры мог использоваться в параллельных процессах), фреймы для неё должны размещаться в стекоподобной структуре данных - "стеке". А поскольку процедурные языки ближе к "естественному" мышлению, то в наборы инструкций процессоров и ассемблеры вводят поддержку подобных высокоуровневых конструкций.

  Существуют нюансы и различия в реализациях, например:

  • Писюковые сишные компиляторы генерят код, в котором часть фрейма с аргументами после вызова процедуры удаляется вызывающим кодом, а в паскалевских соглашениях о вызове фрейм всегда удаляется самой процедурой (что экономит на размере кода, поэтому это соглашение было принято как стандартное в Windows).
  • В Паскале существует понятие локальных процедур, которые могут обращаться к параметрам и локальным переменным всех родительских (в смысле статического размещения, а не динамического порядка вызовов) процедур и при этом могут быть рекурсивными (родительские процедуры тоже могут быть рекурсивными, и доступ к переменным должен идти к последнему, активному экземпляру). Для поддержки этой идеи во фреймы добавляются указатели на родительские фреймы, обычно организованные в виде списка.
  • Фортран вообще язык не рекурсивный, поэтому IBM в реализации Фортрана на IBM/360 (где, кстати, нет поддержки стека) для каждой процедуры заводила фрейм статически, во время компиляции.

  Подобные "нюансы" сущности фрейма, конечно же, не меняют. Приведены они по одной единственной причине – чтобы вы поняли некоторую условность такого термина как "фрейм".

  Теперь, собсна, про ebp/ep. В случае стекового фрейма его адрес не фиксирован, поэтому адресация параметров и переменных в нём должна быть "базисно-индексной", относительно начала фрейма. На писюке под это идеально подошёл (или изначально проектировался) BP/EBP - в отличие от SP, он может служить базой, и также адресуется относительно SS.

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




Содержание  Назад  Вперед