2012-06-09 2 views
2

Я, безусловно, не специалист по ассемблерам, и мои знания по этой теме довольно мелкие, но мне было любопытно, что делает компилятор Microsoft VC++ в простом вызове функции, который ничего не возвращает, но возвращает значение.Ассемблер: код ассемблера «Function Call», созданный VC++

Давайте следующую функция:

unsigned long __stdcall someFunction (void * args) { 
    return 0; 
} 

Теперь я знаю, что с __stdcall вызывающих конвенциями вызываемого абонент отвечает за стек разматывание, и с __cdecl вызвавшей функции заботится об этом. Но для этого примера я хотел бы придерживаться первого.

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

unsigned long __stdcall someFunction (void * args) { 
00A31730 push  ebp 
00A31731 mov   ebp,esp 
00A31733 sub   esp,0C0h 
00A31739 push  ebx 
00A3173A push  esi 
00A3173B push  edi 
00A3173C lea   edi,[ebp-0C0h] 
00A31742 mov   ecx,30h 
00A31747 mov   eax,0CCCCCCCCh 
00A3174C rep stos dword ptr es:[edi] 
    return 0; 
00A3174E xor   eax,eax 
} 
00A31750 pop   edi 
00A31751 pop   esi 
00A31752 pop   ebx 
00A31753 mov   esp,ebp 
00A31755 pop   ebp 
00A31756 ret   4 

Я бы отблагодарить никому объяснить этот фрагмент кода для меня, если это возможно. Я знаю, что оператор xor действительно сбрасывает регистр eax для получения нулевого значения возврата. Также мне кажется, что ret 4. Я думаю, что регистры , esi и ebx выталкиваются и записываются после сохранения исходного состояния, так что функция может свободно их использовать. Но для остальных - я понятия не имею.

Любой ответ очень ценится! :)

Спасибо!

+2

Он полностью удалит функцию, поскольку она не делает ничего полезного. Нет смысла смотреть на код, созданный конфигурацией Debug, большая часть того, что вы разместили, из-за опции/RTC. –

+0

Да, я знаю об этом :) Это действительно вопрос только о самой логике, как компилятор VC строит в этом случае конструкцию необработанных функций - даже если она удаляется во время оптимизации. – PuerNoctis

ответ

3

Так вы спрашиваете, что эти линии делают:

00A3173C lea   edi,[ebp-0C0h] 
00A31742 mov   ecx,30h 
00A31747 mov   eax,0CCCCCCCCh 
00A3174C rep stos dword ptr es:[edi] 

В Visual C++ отладки библиотеки времени выполнения, неинициализированная память инициализации стеки содержит 0xCC байт. Вот что делают эти инструкции.

В начале кода ASM имеется инструкция sub esp,0C0h, которая выделяет для стека байтов. Однако в этой функции нет локальных переменных, поэтому откуда это происходит? Это для поддержки Edit + Continue: вы можете добавлять локальные переменные и продолжать отладку.

0xCC опкода означает инструкцию по сборке INT 3 x86, так что если вы попытаетесь выполнить этот код (случайно из-за ошибки), то программа выдаст INT 3 исключения, которое будет обрабатываться с помощью отладчика или OS. Так что это не просто случайное значение.

+0

Хотя вы правы в том, что делает код, я не уверен в части INT 3. У вас есть ссылка на эту информацию? – James

+0

Спасибо за ответ. Я столкнулся с этими байтами '0xCC' довольно много, когда сталкивался с нарушениями прав доступа, и уже несколько дней назад прочитал о INT 3 и как их используют отладчики. Но, если возможно, не могли бы вы быть более конкретными в этих четырех строках? Почему 'edi' загружается' [ebp-0C0h] '? Это значение также кажется не случайным. Или почему 'ecx' заполнен' 0x30'? Я не хочу быть болью в нижней части, извините за мою формулировку, но я хотел бы узнать об этом немного больше :) – PuerNoctis

+2

Недостающий ингредиент - это Edit + Continue.Структура Debug over-выделяет пространство стека, поэтому вы можете добавлять локальные переменные и продолжать отладку. –