странный уровень косвенности вызова функции - PullRequest
2 голосов
/ 28 августа 2011

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

__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
}

__declspec(noinline) int test123()
{
    char buf[123];
    return get_alignment(buf);
}

Затем, когда я перехожу код внутри функции test () в отладчике в режиме asm (Ctrl + F11), я вижу это:

__declspec(noinline) int test123()
{
0041FA70  sub         esp,7Ch 
    char buf[123];
    return get_alignment(buf);
0041FA73  lea         eax,[esp] 
0041FA76  push        eax  
0041FA77  call        get_alignment (40A38Fh) 
}
...
get_alignment:
0040A38F  jmp         get_alignment (41FA60h) 
...
__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
0041FA60  mov         eax,1 
}

Итак, вопрос об этом дополнительном уровне косвенности: get_alignment: 0040A38F jmp get_alignment (41FA60h)

WTF это о чем ?!Я просто не понимаю, это не импортированная функция из dll, это локальная функция, определенная в исполняемом файле.Этот исполняемый файл скомпилирован со всеми видами оптимизаций (кроме генерации временного кода ссылки).Если я добавлю static к объявлению этого get_alignment, то эта дополнительная косвенность исчезнет.Но я не ищу «исправления», я просто хотел понять, почему этот дополнительный переход вообще существует!

В моем реальном приложении я фактически использую функцию, написанную в файле .asm, и я простоне понимаю, почему генерируется дополнительный прыжок.Похоже, что если я скомпилирую свой код в C-режиме (не в C ++), то я больше не вижу такого уровня косвенности ...

Кто-нибудь может пролить свет на это странное поведение?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 28 августа 2011

Это побочный эффект опции компоновщика / INCREMENTAL.Который включает инкрементное связывание и Edit + Continue.Переход используется, когда вы редактируете код во время работы программы.Функция замены скомпилирована по другому адресу, а цель jmp пропатчена, чтобы указать на новую функцию.Инкрементное связывание использует это также, чтобы избежать необходимости воссоздавать двоичное изображение с нуля.

2 голосов
/ 28 августа 2011

Возможно, у вас включено инкрементное связывание. Инкрементно связанный модуль «Может содержать переходные последовательности для управления перемещением функций на новые адреса». http://msdn.microsoft.com/en-US/library/4khtbfyf(v=VS.80).aspx

1 голос
/ 28 августа 2011

Короче говоря, в моем случае было включено добавочное связывание, потому что я не отключил его явно для своей сборки. В общем, параметры компоновщика отключают инкрементное связывание, чтобы избежать дополнительного перехода (/ INCREMENTAL: NO option)

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