компилирую прогу с использованием gcc 3.4.5 с параметрами: -O2 -fomit-frame-pointer стек-фреймы действительно отключаются, но, непонятно мне, зачем компилятор делает так: Код (Text): test: sub esp,n ; ... add esp,n ret причем, локальных переменных нет, а параметры передаются через регистры (fastcall), но не более 2 параметров. (используются edx и ecx) то есть передача параметров через стек не используется. тогда зачем нужен этот пролог/эпилог из sub esp,n / add esp,n число n может варьироваться.
Microedition > gcc ... число n может варьироваться Не выравнивает ли он стек на 16-тибайтную границу?
ну, например: Код (Text): 00000020 ; int __fastcall matrix2x2_alloc() 00000020 public @matrix2x2_alloc@0 00000020 @matrix2x2_alloc@0 proc near 00000020 sub esp, 0Ch 00000023 mov ecx, 10h 00000028 call @rtl_malloc@4 ; rtl_malloc(x) 0000002D mov ecx, eax 0000002F add esp, 0Ch 00000032 jmp short @matrix2x2_init@4 ; matrix2x2_init(x) 00000032 @matrix2x2_alloc@0 endp ; sp-analysis failed или вот: Код (Text): 00000080 ; __fastcall list_free(x) 00000080 public @list_free@4 00000080 @list_free@4 proc near 00000080 push ebx 00000081 sub esp, 8 00000084 mov ebx, ecx 00000086 call @list_clear@4 ; list_clear(x) 0000008B add esp, 8 0000008E mov ecx, ebx 00000090 pop ebx 00000091 jmp @rtl_free@4 ; rtl_free(x) 00000091 @list_free@4 endp
а вот листинг matrix2x2_init(): Код (Text): 00000000 ; __fastcall matrix2x2_init(x) 00000000 public @matrix2x2_init@4 00000000 @matrix2x2_init@4 proc near ; CODE XREF: matrix2x2_alloc() 00000000 mov eax, 0 00000005 mov edx, 3F800000h 0000000A mov [ecx+4], eax 0000000D mov [ecx+8], eax 00000010 mov eax, ecx 00000012 mov [ecx], edx 00000014 mov [ecx+0Ch], edx 00000017 retn 00000017 @matrix2x2_init@4 endp
открой для себя еще -mregparm=3 и не надо будет писать никакого __fastcall Код (Text): #include <inttypes.h> #include <stdio.h> __int64 xz (__int64 my, int x) { return my >> x; } int main (void) { printf ("%x", xz(0x123456789ABCDEF0,48)); } .file "my.c" .intel_syntax .text .p2align 4,,15 .globl _xz .def _xz; .scl 2; .type 32; .endef _xz: shrd eax, edx, cl sar edx, cl test cl, 32 je L2 mov eax, edx sar edx, 31 L2: ret .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "%x\0" .text .p2align 4,,15 .globl _main .def _main; .scl 2; .type 32; .endef _main: push ebp mov eax, 16 mov ebp, esp sub esp, 24 and esp, -16 call __alloca call ___main mov ecx, 48 mov eax, -1698898192 mov edx, 305419896 call _xz mov DWORD PTR [esp+4], eax mov DWORD PTR [esp+8], edx mov DWORD PTR [esp], OFFSET FLAT:LC0 call _printf leave ret .def _printf; .scl 2; .type 32; .endef в принципе xz красотищща (и пофик на main) а да ключи компиляния *.S сорц проги: gcc -S -mregparm=3 -O2 -mconsole -momit-leaf-frame-pointer -masm=intel my.c собственно маленькая ексешка: gcc -s -mregparm=3 -O2 -mconsole -momit-leaf-frame-pointer -masm=intel my.c
Microedition Можно предположить, что gcc заботится о размещении адрес возврата из подпрограммы на 16-байтной границе. В int __fastcall matrix2x2_alloc() команда sub esp, 0Ch заботится об адресе возврата из rtl_malloc. В __fastcall list_free(x) есть push ebx, поэтому sub esp, 8. В __fastcall matrix2x2_init(x) нет вызовов подпрограмм, поэтому нет манипуляций с регистром esp.
q_q да, действительно, там, где нет вызовов подпрограмм и нет локальных переменных, esp не изменяется. ну а __fastcall matrix2x2_alloc() вообще-то возвращяет указатель, но это и не важно.
Microedition > __fastcall matrix2x2_alloc() вообще-то возвращяет указатель Ты понял не до конца. Об адресе возврата заботится вызывающая сторона. Про int __fastcall matrix2x2_alloc() я написал, что она "заботится об адресе возврата из rtl_malloc".
хмм.. не забывайте, что все функции передают параметры через регистры (fastcall). а rtl_malloc принимает один аргумент типа dword (в ecx) и возвращает dword.. так что манипуляции с указателем стека не нужны. или я туплю, т.к. день не спал.
Microedition > манипуляции с указателем стека не нужны Что непонятно в первом предложении #6? > программа нормально работает А надо было оптимально, правда, критерии (скорость/размер) не озвучены. Например, с точки зрения скорости обработки данных будет лучше, если данные будут лежать по адресам кратным 16-ти.