Лекция № 4
DESCRIPTION
Лекция № 4. Процедуры. План. Модификатор static О программировании: Точки следования Типизация Контексты Стековые фреймы Соглашения вызова. static. Помечаем функции и переменные Инициализируются один раз, находятся в сегменте данных Доступ к ним только из текущего файла - PowerPoint PPT PresentationTRANSCRIPT
Лекция № 4Процедуры
1
План•Модификатор static•О программировании:
▫Точки следования▫Типизация▫Контексты
•Стековые фреймы•Соглашения вызова
2
static•Помечаем функции и переменные•Инициализируются один раз, находятся в
сегменте данных•Доступ к ним только из текущего файла•Выпадают из таблицы экспорта (следствие).•В C все нестатические функции находятся в
таблицах экспорта (а те, для которых указываются сигнатуры без тела, включаются в таблицу импорта текущего модуля).
3
static•Как у нас сохраняется значение:void func () {
static int counter = 0;counter++;printf("%d\n", counter);
}int main (int argc, char** argv ) {
func();func();func();
}Выведет: 1 2 3
4
Точки следованияint a = 4;a = ++ a + a;printf(“%d”, a);
Что выведется на экран?
5
Еще примеры• i = v[i++];•void f(int, int);
int g() {puts(“g”);}int h() {puts(“h”);}f(g(), h()) {}
Выведет g h или h g ?
6
Точки следованияГде абстрактный вычислитель в том же
состоянии, что и конкретный. - Все побочные эффекты предыдущих
выражений применены.- Все побочные эффекты следующих
выражений еще не наступили.
7
Где они? Стандарт 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).
8
Где они? Стандарт C:•В конце вычисления полного
выражения (которое не является ничьим подвыражением)
•После вычисления первого из двух операндов для ||, &&, запятой и для тернарного ?:
•После вычисления аргументов функции (непосредственно перед её вызовом)
9
Типизация•Строгая и нестрогая•Статическая и динамическая
•Например, в C статическая и нестрогая.
10
Контексты•Статический: что нам точно доступно в
данном месте программы исходя из её структуры.
•Динамический: что нам доступно исходя из того, что «программа так выполняется»
11
int some_global = 4;
func2() {}
func3() {int int_3func1();
}
void func1() {int int_1; //доступ только к int_1 и globalfunc2();func3();
}
void main ( int argc , char** argv ) {int int_main; //отсюда есть доступ к global и int_mainfunc1();
}
12
Stack frame
13
Состояние стека.funcA вызывает funcB, которая вызывает
funcC
Вызов процедуры•High level way (stack frame, механизм
стекового кадра)•Возвращаемое значение обычно в EAX
14
Stack frame
15
1. Поместить аргументы в стек (push)2. Вызвать функцию с помощью команды call (в
стеке сохранится адрес возврата)3. Сохранить предыдущее значение EBP в стеке
(начало предыдущего стекового фрейма)4. ESP->EBP; EBP теперь обозначает «начало
стекового кадра» и используется для адресации аргументов и локальных переменных.
5. Выделяем память в стеке для локальных переменных (уменьшить ESP на их суммарный размер)
Stack frame
16
void myproc(int argument1) {int a, b;/*код*/ }
Вызываем функцию:myproc(42);1. push argument1 (42)2. call myproc3. push ebp4. mov ebp, esp5. sub esp, 8
Рост стека
argument1 = 42
Адрес возврата
Начало предыдущего кадра
8 байт под локальные
переменные
EBP
ESP
Calling conventions•Где аргументы, где возвращаемое
значение?•Порядок передачи параметров.•Кто возвращает указатель стека на
исходную позицию•Какой командой вызывать
подпрограмму и какой — возвращаться в основную программу.
•Какие регистры восстанавливает
17
Calling conventions•Где аргументы, где возвращаемое
значение?▫Стек▫Регистры▫Общая память (глобальные переменные)
18
Calling conventions•Порядок передачи параметров.
▫Прямой▫Обратный
19
Calling conventions•Кто возвращает указатель стека на
исходную позицию▫Сама процедура▫Вызывающая программа
20
Calling conventions•Какой командой вызывать
подпрограмму и какой — возвращаться в основную программу.▫call near - retn == ret▫call far - retf ▫pushf + call far - iret
21
Calling conventions•Соглашения вызоваИспользуются следующие:
▫C▫Pascal▫stdcall▫fastcallДругие:▫safecall▫thiscall
22
Calling convention: C•Параметры помещаются в стек справа
налево•Значение SP восстанавливается после
выхода из процедуры
23
Calling convention: Pascal•Параметры помещаются в стек слева
направо•Значение SP восстанавливается в самой
процедуре с помощью аргумента ret
24
Calling convention: stdcall•Параметры помещаются в стек справа
налево (как в С)•Значение SP восстанавливается в самой
процедуре с помощью аргумента ret (как в Pascal)
•Почти всегда используется для Windows API
25
Calling conventions•Используются модификаторы
▫_stdcall▫_cdecl▫_pascal▫_fastcall (параметры передаются через
регистры)•Напримерint _cdecl main(int argc, char** argv)
26
Простая программаint _cdecl main(int argc, char** argv) {
int result = 0;char* str = "stringy!";result++;
return 0; }
27
TITLE f:\??????\?????????\Visual Studio 2008\Projects\simple\simple\main.c.686Pinclude listing.inc.model flat
INCLUDELIB OLDNAMES$SG-5 DB 'stringy!', 00HPUBLIC _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
28
; 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 ENDSEND
29
TITLE f:\??????\?????????\Visual Studio 2008\Projects\simple\simple\main.c.686Pinclude listing.inc.model flat
INCLUDELIB OLDNAMES$SG-5 DB 'stringy!', 00HPUBLIC _main_TEXT SEGMENT_str$ = -8 ; size = 4_result$ = -4 ; size = 4_argc$ = 8 ; size = 4_argv$ = 12 ; size = 4_main PROC ; COMDAT
30
; 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
31
Программа с 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;
}
32
INCLUDELIB OLDNAMES
EXTRN _printf:PROC$SG-5 DB 'stringy!', 00H
ORG $+3 ;Директива ORG – ассемблирование начнётся по новому адресу. $ - текущий адрес
$SG-6 DB '%d', 00H
33
Программа с 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;
}
34
_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
35
Программа с 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;
}
36
из функции 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
37