Лекция № 4

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

Upload: connor

Post on 19-Mar-2016

58 views

Category:

Documents


3 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Лекция № 4

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

1

Page 2: Лекция № 4

План•Модификатор static•О программировании:

▫Точки следования▫Типизация▫Контексты

•Стековые фреймы•Соглашения вызова

2

Page 3: Лекция № 4

static•Помечаем функции и переменные•Инициализируются один раз, находятся в

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

таблицах экспорта (а те, для которых указываются сигнатуры без тела, включаются в таблицу импорта текущего модуля).

3

Page 4: Лекция № 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

4

Page 5: Лекция № 4

Точки следованияint a = 4;a = ++ a + a;printf(“%d”, a);

Что выведется на экран?

5

Page 6: Лекция № 4

Еще примеры• i = v[i++];•void f(int, int);

int g() {puts(“g”);}int h() {puts(“h”);}f(g(), h()) {}

Выведет g h или h g ?

6

Page 7: Лекция № 4

Точки следованияГде абстрактный вычислитель в том же

состоянии, что и конкретный. - Все побочные эффекты предыдущих

выражений применены.- Все побочные эффекты следующих

выражений еще не наступили.

7

Page 8: Лекция № 4

Где они? Стандарт 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

Page 9: Лекция № 4

Где они? Стандарт C:•В конце вычисления полного

выражения (которое не является ничьим подвыражением)

•После вычисления первого из двух операндов для  ||, &&, запятой и для тернарного ?:

•После вычисления аргументов функции (непосредственно перед её вызовом)

9

Page 10: Лекция № 4

Типизация•Строгая и нестрогая•Статическая и динамическая

•Например, в C статическая и нестрогая.

10

Page 11: Лекция № 4

Контексты•Статический: что нам точно доступно в

данном месте программы исходя из её структуры.

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

11

Page 12: Лекция № 4

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

Page 13: Лекция № 4

Stack frame

13

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

funcC

Page 14: Лекция № 4

Вызов процедуры•High level way (stack frame, механизм

стекового кадра)•Возвращаемое значение обычно в EAX

14

Page 15: Лекция № 4

Stack frame

15

1. Поместить аргументы в стек (push)2. Вызвать функцию с помощью команды call (в

стеке сохранится адрес возврата)3. Сохранить предыдущее значение EBP в стеке

(начало предыдущего стекового фрейма)4. ESP->EBP; EBP теперь обозначает «начало

стекового кадра» и используется для адресации аргументов и локальных переменных.

5. Выделяем память в стеке для локальных переменных (уменьшить ESP на их суммарный размер)

Page 16: Лекция № 4

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

Page 17: Лекция № 4

Calling conventions•Где аргументы, где возвращаемое

значение?•Порядок передачи параметров.•Кто возвращает указатель стека на

исходную позицию•Какой командой вызывать

подпрограмму и какой — возвращаться в основную программу.

•Какие регистры восстанавливает

17

Page 18: Лекция № 4

Calling conventions•Где аргументы, где возвращаемое

значение?▫Стек▫Регистры▫Общая память (глобальные переменные)

18

Page 19: Лекция № 4

Calling conventions•Порядок передачи параметров.

▫Прямой▫Обратный

19

Page 20: Лекция № 4

Calling conventions•Кто возвращает указатель стека на

исходную позицию▫Сама процедура▫Вызывающая программа

20

Page 21: Лекция № 4

Calling conventions•Какой командой вызывать

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

21

Page 22: Лекция № 4

Calling conventions•Соглашения вызоваИспользуются следующие:

▫C▫Pascal▫stdcall▫fastcallДругие:▫safecall▫thiscall

22

Page 23: Лекция № 4

Calling convention: C•Параметры помещаются в стек справа

налево•Значение SP восстанавливается после

выхода из процедуры

23

Page 24: Лекция № 4

Calling convention: Pascal•Параметры помещаются в стек слева

направо•Значение SP восстанавливается в самой

процедуре с помощью аргумента ret

24

Page 25: Лекция № 4

Calling convention: stdcall•Параметры помещаются в стек справа

налево (как в С)•Значение SP восстанавливается в самой

процедуре с помощью аргумента ret (как в Pascal)

•Почти всегда используется для Windows API

25

Page 26: Лекция № 4

Calling conventions•Используются модификаторы

▫_stdcall▫_cdecl▫_pascal▫_fastcall (параметры передаются через

регистры)•Напримерint _cdecl main(int argc, char** argv)

26

Page 27: Лекция № 4

Простая программаint _cdecl main(int argc, char** argv) {

int result = 0;char* str = "stringy!";result++;

return 0; }

27

Page 28: Лекция № 4

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

Page 29: Лекция № 4

; 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

Page 30: Лекция № 4

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

Page 31: Лекция № 4

; 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

Page 32: Лекция № 4

Программа с 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

Page 33: Лекция № 4

INCLUDELIB OLDNAMES

EXTRN _printf:PROC$SG-5 DB 'stringy!', 00H

ORG $+3 ;Директива ORG – ассемблирование начнётся по новому адресу. $ - текущий адрес

$SG-6 DB '%d', 00H

33

Page 34: Лекция № 4

Программа с 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

Page 35: Лекция № 4

_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

Page 36: Лекция № 4

Программа с 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

Page 37: Лекция № 4

из функции 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