1 / 37

Лекция № 4

Лекция № 4. Процедуры. План. Модификатор static О программировании: Точки следования Типизация Контексты Стековые фреймы Соглашения вызова. static. Помечаем функции и переменные Инициализируются один раз, находятся в сегменте данных Доступ к ним только из текущего файла

connor
Download Presentation

Лекция № 4

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Лекция № 4 Процедуры

  2. План • Модификатор static • О программировании: • Точки следования • Типизация • Контексты • Стековые фреймы • Соглашения вызова

  3. static • Помечаем функции и переменные • Инициализируются один раз, находятся в сегменте данных • Доступ к ним только из текущего файла • Выпадают из таблицы экспорта (следствие). • В C все нестатические функции находятся в таблицах экспорта (а те, для которых указываются сигнатуры без тела, включаются в таблицу импорта текущего модуля).

  4. static • Как у нас сохраняется значение: void func () { static int counter = 0; counter++; printf("%d\n", counter); } int main (int argc, char** argv ) { func(); func(); func(); } Выведет: 1 2 3

  5. Точки следования int a = 4; a = ++ a + a; printf(“%d”, a); Что выведется на экран?

  6. Еще примеры •  i = v[i++]; • void f(int, int);int g(){puts(“g”);}int h() {puts(“h”);}f(g(), h()) {} Выведет g h или h g ?

  7. Точки следования Где абстрактный вычислитель в том же состоянии, что и конкретный. • Все побочные эффекты предыдущих выражений применены. • Все побочные эффекты следующих выражений еще не наступили.

  8. Где они? Стандарт C: • at the end of the evaluation of a full expression (a full expression is an expression statement, or any other expression which is not a subexpression within any larger expression); • at the ||, &&, ?:, and comma operators; • at a function call (after the evaluation of all the arguments, and just before the actual call).

  9. Где они? Стандарт C: • В конце вычисления полного выражения (которое не является ничьим подвыражением) • После вычисления первого из двух операндов для  ||, &&, запятой и для тернарного ?: • После вычисления аргументов функции (непосредственно перед её вызовом)

  10. Типизация • Строгая и нестрогая • Статическая и динамическая • Например, в C статическая и нестрогая.

  11. Контексты • Статический: что нам точно доступно в данном месте программы исходя из её структуры. • Динамический: что нам доступно исходя из того, что «программа так выполняется»

  12. int some_global = 4; func2() {} func3() { int int_3 func1(); } void func1() { int int_1; //доступ только к int_1 и global func2(); func3(); } void main ( int argc , char** argv ) { int int_main; //отсюда есть доступ к global и int_main func1(); }

  13. Stack frame Состояние стека. funcAвызывает funcB, которая вызывает funcC

  14. Вызов процедуры • High level way (stack frame, механизм стекового кадра) • Возвращаемое значение обычно в EAX

  15. Stack frame • Поместить аргументы в стек (push) • Вызвать функцию с помощью команды call (в стеке сохранится адрес возврата) • Сохранить предыдущее значение EBP в стеке (начало предыдущего стекового фрейма) • ESP->EBP; EBP теперь обозначает «начало стекового кадра» и используется для адресации аргументов и локальных переменных. • Выделяем память в стеке для локальных переменных (уменьшить ESP на их суммарный размер)

  16. Stack frame Рост стека void myproc(int argument1) { int a, b; /*код*/ } Вызываем функцию: myproc(42); • push argument1 (42) • call myproc • push ebp • mov ebp, esp • sub esp, 8 ESP 8 байт под локальные переменные Начало предыдущего кадра EBP Адрес возврата argument1 = 42

  17. Calling conventions • Где аргументы, где возвращаемое значение? • Порядок передачи параметров. • Кто возвращает указатель стека на исходную позицию • Какой командой вызывать подпрограмму и какой — возвращаться в основную программу. • Какие регистры восстанавливает

  18. Calling conventions • Где аргументы, где возвращаемое значение? • Стек • Регистры • Общая память (глобальные переменные)

  19. Calling conventions • Порядок передачи параметров. • Прямой • Обратный

  20. Calling conventions • Кто возвращает указатель стека на исходную позицию • Сама процедура • Вызывающая программа

  21. Calling conventions • Какой командой вызывать подпрограмму и какой — возвращаться в основную программу. • call near - retn == ret • call far - retf • pushf + call far - iret

  22. Calling conventions • Соглашения вызова Используются следующие: • C • Pascal • stdcall • fastcall Другие: • safecall • thiscall

  23. Calling convention: C • Параметры помещаются в стек справа налево • Значение SP восстанавливается после выхода из процедуры

  24. Calling convention: Pascal • Параметры помещаются в стек слева направо • Значение SP восстанавливается в самой процедуре с помощью аргумента ret

  25. Calling convention: stdcall • Параметры помещаются в стек справа налево (как в С) • Значение SP восстанавливается в самой процедуре с помощью аргумента ret (как в Pascal) • Почти всегда используется для Windows API

  26. Calling conventions • Используются модификаторы • _stdcall • _cdecl • _pascal • _fastcall(параметры передаются через регистры) • Например int _cdecl main(int argc, char** argv)

  27. Простая программа int _cdecl main(int argc, char** argv) { int result = 0; char* str = "stringy!"; result++; return 0; }

  28. TITLE f:\??????\?????????\Visual Studio 2008\Projects\simple\simple\main.c .686P include listing.inc .model flat INCLUDELIB OLDNAMES $SG-5 DB 'stringy!', 00H PUBLIC _main _TEXT SEGMENT _str$ = -8 ; size = 4 _result$ = -4 ; size = 4 _argc$ = 8 ; size = 4 _argv$ = 12 ; size = 4 _main PROC ; COMDAT ; 1 : int _cdecl main(int argc, char** argv) { 00000 55 push ebp 00001 8b ec mov ebp, esp 00003 83 ec 08 sub esp, 8

  29. ; 2 : int result = 0; 00006 c7 45 fc 00 00 00 00 mov DWORD PTR _result$[ebp], 0 ; 3 : char* str = "stringy!"; 0000d c7 45 f8 00 00 00 00 mov DWORD PTR _str$[ebp], OFFSET $SG-5 ; 4 : result++; 00014 8b 45 fc mov eax, DWORD PTR _result$[ebp] 00017 83 c0 01 add eax, 1 0001a 89 45 fc mov DWORD PTR _result$[ebp], eax ; 5 : return 0; 0001d 33 c0 xor eax, eax ; 6 : } 0001f 8b e5 mov esp, ebp 00021 5d pop ebp 00022 c3 ret 0 _main ENDP _TEXT ENDS END

  30. TITLE f:\??????\?????????\Visual Studio 2008\Projects\simple\simple\main.c .686P include listing.inc .model flat INCLUDELIB OLDNAMES $SG-5 DB 'stringy!', 00H PUBLIC _main _TEXT SEGMENT _str$ = -8 ; size = 4 _result$ = -4 ; size = 4 _argc$ = 8 ; size = 4 _argv$ = 12 ; size = 4 _main PROC ; COMDAT

  31. ; 1 : int _cdecl main(int argc, char** argv) { 00000 55 push ebp 00001 8b ec mov ebp, esp 00003 83 ec 08 sub esp, 8;sizeof(int) + sizeof(char*) = 4 + 4 = 8 ; 2 : int result = 0; 00006 c7 45 fc 00 00 00 00 mov DWORD PTR _result$[ebp], 0 ; 3 : char* str = "stringy!"; 0000d c7 45 f8 00 00 00 00 mov DWORD PTR _str$[ebp], OFFSET $SG-5 ; 4 : result++; 00014 8b 45 fc mov eax, DWORD PTR _result$[ebp] 00017 83 c0 01 add eax, 1 0001a 89 45 fc mov DWORD PTR _result$[ebp], eax ; 5 : return 0; 0001d 33 c0 xor eax, eax ; 6 : } 0001f 8b e5 mov esp, ebp 00021 5d pop ebp 00022 c3 ret 0 _main ENDP _TEXT ENDS// затем END

  32. Программа с printf и дополнительной функцией void printf(const char*, ...); int _cdecl foosize (char* param_str) { register int size = 0; while(param_str[size++]); return size; } int _cdecl main(int argc, char** argv) { int result = 0; char* str = "stringy!"; result = foosize(str); printf("%d",result); return 0; }

  33. INCLUDELIB OLDNAMES EXTRN _printf:PROC $SG-5 DB 'stringy!', 00H ORG $+3;Директива ORG – ассемблирование начнётся по новому адресу. $ - текущий адрес $SG-6 DB '%d', 00H

  34. Программа с printf и дополнительной функцией void printf(const char*, ...); int _cdecl foosize (char* param_str) { register int size = 0; while(param_str[size++]); return size; } int _cdecl main(int argc, char** argv) { int result = 0; char* str = "stringy!"; result = foosize(str); printf("%d",result); return 0; }

  35. _TEXT SEGMENT _size$ = -4 ; size = 4 _param_str$ = 8 ; size = 4 _foosize PROC ; COMDAT ; 3 : int _cdecl foosize (char* param_str) { 00000 55 push ebp 00001 8b ec mov ebp, esp 00003 51 push ecx ; 4 : register int size = 0; 00004 c7 45 fc 00 00 00 00 mov DWORD PTR _size$[ebp], 0 $LN2@foosize: ; 5 : while(param_str[size++]); /* код для while*/ ; 6 : return size; 00023 8b 45 fc mov eax, DWORD PTR _size$[ebp] ; 7 : } 00026 8b e5 mov esp, ebp 00028 5d pop ebp 00029 c3 ret 0 _foosize ENDP

  36. Программа с printf и дополнительной функцией void printf(const char*, ...); int _cdecl foosize (char* param_str) { register int size = 0; while(param_str[size++]); return size; } int _cdecl main(int argc, char** argv) { int result = 0; char* str = "stringy!"; result = foosize(str); printf("%d",result); return 0; }

  37. из функции main ; 13 : result = foosize(str); 00014 8b 45 f8 mov eax, DWORD PTR _str$[ebp] 00017 50 push eax 00018 e8 00 00 00 00 call _foosize 0001d 83 c4 04 add esp, 4 00020 89 45 fc mov DWORD PTR _result$[ebp], eax ; 14 : printf("%d",result); 00023 8b 4d fc mov ecx, DWORD PTR _result$[ebp] 00026 51 push ecx 00027 68 00 00 00 00 push OFFSET $SG-6 0002c e8 00 00 00 00 call _printf 00031 83 c4 08 add esp, 8 ; 15 : return 0; 00034 33 c0 xor eax, eax

More Related