Как работает импорт в программах?

Разбирался как работает импорт и непонятна одна вещь.Но все по порядку.Когда мы в программе вызываем какую то функцию,имя этой функции является адресом функции.Так...Если написать такой код:

  std::cout << Beep << std::endl;

Мы получим адрес функции Beep из подгруженной библиотеки kernel32.dll.Но откуда берется этот адрес?Как программа знает где загружена эта функция,точнее ее адрес?Я знаю, что адрес можно получить из таблицы импорта,ссылавшись на поле FirstThunk структуры _IMAGE_IMPORT_DESCRIPTOR,но смотря на дизассемблер,там адрес функции выглядит примерно так: qword ptr ds:[<&Beep>] .Читаю про регистр ds,он должен ссылаться на секцию данных.Смотрю на регистр,он у меня: DS 002B. C этого момента я в тупике.Ведь,что это за смещение такое "002B", оно ведь слишком маленькое,откуда его отсчитывать..Мне крайне непонятен механизм импорта и связывания функций.


Ответы (1 шт):

Автор решения: MSDN.WhiteKnight

Если написать такой код ... Мы получим адрес функции Beep из подгруженной библиотеки kernel32.dll

То, что выведет код std::cout << Beep, далеко не обязательно реальный адрес функции, причины описаны здесь: Что такое адрес функции?

Читаю про регистр ds,он должен ссылаться на секцию данных

Скорее всего, это просто ошибка дизассемблера, с чего бы адресу функции быть в секции данных? У меня вызов функции Beep превращается вот в такое в выводе dumpbin /disasm:

FF 15 00 B0 41 00  call dword ptr [__imp__Beep@8]

Код инструкции FF 15 (с учетом opcode extensions) здесь обозначает "Call near, absolute indirect, address given in r/m32" - т.е. вызов функции по адресу в заданной ячейке памяти (см. https://c9x.me/x86/html/file_module_x86_id_26.html). Операнд 00 B0 41 00 - сам адрес (перевернутый). Человеко-читаемый адрес тут будет: 0x41B000. Смотрим в выводе dumpbin секции:

SECTION HEADER #5
  .idata name
     CDF virtual size
   1B000 virtual address (0041B000 to 0041BCDE)

То есть адрес функции ожидаемо попадает в секцию .idata, таблицу импорта. Из вывода dumpbin /imports узнать более точно:

KERNEL32.dll
    41B000 Import Address Table
    41B268 Import Name Table

Как видно, 41B000 - это начало Import Address Table модуля KERNEL32.dll. Эта таблица заполняется загрузчиком ОС при запуске программы, куда он пишет уже реальные адреса функций в загруженных модулях.

→ Ссылка