помогите разобраться - есть такой C код : Код (Text): void foo(void (*f)(void)) { f(); } у меня gcc переводит в асм это примерно так - Код (Text): pushl %ebp movl %esp, %ebp subl $8, %esp movl 8(%ebp), %eax call *%eax leave ret я не могу понять зачем там "sub 8, esp", если ее убрать вылетает сегфолт появляется она только если есть вызов функции (необязательно через указатель) да и если что - у меня Мак, может это из-за этого, я не знаю просто че на остальных платформах получается в асме
k_dmitry В функциях команды типа: Код (Text): push ebp mov ebp, esp sub esp, n это формирование стекового кадра (stack frame) для локальных переменных; иногда применяют Код (Text): enter n, 0 (второй операнд необязательно 0), который выполняет все те же действия. ЗЫ. Не думал, что на wasm-е в разделе ASSEMBLER увижу подобный пост ) ЗЗЫ. Ох уж этот зверский AT&T синтаксис
zhindos так тут же нет локальных переменных. если бы было так, то можно было бы безболезненно убрать, а оно не убирается( листинг полный я ничего не укорачивал
k_dmitry Я очень не люблю синтаксис, который предложила когда-то небезызвестная фирма из 3-х букв,но смею предположить, что страшная фича: Код (Text): movl 8(%ebp), %eax на самом деле не что иное, как: Код (Text): mov eax, dword ptr [ebp] (сбивает с толку 8-ка, но повторяю - i hate AT&T syntax!) А вот теперь и подумай, с какой области стека ты читаешь что-либо в eax, если убрать то, что ты хотел убрать???
zhindos Код (Text): movl 8(%ebp), %eax ~ Код (Text): movl eax, [ebp + 8] это берется параметр ф-ии. после "sub esp, 8" нам доступны [ebp-4] и [ebp-8] a они нигде не используются. тут вся загвостка в call, код ниже работает и возвращает правильный результат Код (Text): pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax leave ret --- че-то я потыкал, и вроде как сегфолт вылетает только если в ф-ии, которая через указатель передается, есть вызовы ф-ий из стд библиотеки, ну там printf, malloc...непонятно ниче. а может кто-нибудь посмотреть в линуксе также? в смысле асм такой же получается?
ура! я нашел ответ)) оказывается у Маков с Интелом хитрая calling convention, они требуют чтобы перед любым call стэк был выровнен по 16 байт, и в моем примере в стэк перед вызовом той ф-ии был push адреса возврата (4 байта) потом EBP (опять 4), ну и потом вычиталось 8 чтоб было все ровно)