이번 Part3의 큰 주제는 쓰레드이다. 쓰레드가 무엇인지 설명하고 쓰레드 프로그래밍에서 가장 중요한 동기화를 공부한다.



: 함수가 호출되는 원리와 호출 될때마다 할당되는 메모리 방식에 대해 이야기 할 것이다. 

1. 절차적 함수 호출(Procedure Call)지원 CPU 모델

: 함수 호출이라는 것은 소프트웨어 적인 무언가에 의해 작동하는 기능으로 이해하는 경향이 강하다.

: 하지만, 함수 호출이라는 기능은 하드웨어 종속적인 부분이 상당수 존재한다.

: CPU에 따라서 함수가 호출되는 방식이 다르다.

* 스택 프레임(Stack Frame)구조

: 함수내 선언된 변수는 스택에 할당된다.

: 함수 호출 과정에서 할당되는 메모리 블록을 스택프레임이라고 한다.

: 해당 함수가 호출되면서 변수가 스택에 할당되는데 이를 스택프레임이라고 하고 함수가 반환되었을 때 이 스택 프레임은 반환되어 접근할 수 없다.

* sp 레지스터

: 지역변수의 메모리 공간을 스택이라고 불리는 이유는 메모리의 구조적인 특성인 First In, First Out 때문이다.

: 스택의 위치를 기억해야 데이터를 쌓거나 반환할 수 있기 때문에, 이를 위해 sp(Stack Pointer)라는 이름의 Register가 존재한다.

: 스택은 주소값이 위에서 아래로, 혹은 아래서 위로 올라가는 구조일 수 있다.

: 호출이 완료된 함수에서 빠져나오는 시점에서 메모리 공간을 얼마나 반환해야 하는지(sp를 밑으로 얼만큼 움직여야하는지) 알 수 없다.

* 프레임 포인터(Frame Pointer) 레지스터

: 나중에 되돌아갈 sp의 위치를 저장해 놓는 레지스터이다.

: 함수 호출이 일어날 때 마다 fp 레지스터에 저장되어 있는 값을 스택에 저장한다. 이로써 함수를 중복 호출했을때의 문제를 해결 할 수 있다.

2. 함수 호출 인자의 전달과 PUSH & POP 명령어 디자인

: 함수 호출과 프로시저(Procedure) 호출의 차이는 반환값의 유무로도 볼 수 있다.

함수 호출 시 실행 위치의 이동은 어떻게 이뤄지는가?

함수 호출 시 전달되는 인자들은 어떻게 함수 내부로 전달되는가?

함수 호출이 끝나고 나면 어떻게 이전 실행위치로 복귀하는가?

* 함수 호출 인자의 전달방식

: 지역변수와 마찬가지로 스택에 할당한다.

: 성능향상을 위해 일부 전달 인자들은 레지스터를 할당하도록 제품의 표준을 정의하기도 한다.

* PUSH & POP 명령어 디자인

3. 함수 호출(Procedure Call)에 의한 실행의 이동

* 다시 살펴보는 메모리 구조와 프로그램 카운터

: 프로그램을 실행시키면 위와 같은 메모리 구조가 형성되고 Code 영역에 실행되어야 할 명령어들이 올라가서 순차적인 실행이 이뤄지게 된다.

: 코드영역에 올라간 다음부터 명령어는 Fetch, Decode, Execution된다.

: CPU가 메모리 영역 중 스택을 컨트롤하기 위해서 sp 레지스터를 둔 것처럼, 명령어를 순차적으로 fetch하기 위해서 프로그램 카운터라 불리는 pc 레지스터를 둔다.

: pc 레지스터는 CPU가 자동으로 Fetch, Decode, Execution 과정을 진행하기 때문에 조절하지 않아도 되지만, 경우에 따라서 직접 조절해야하는 경우도 발생한다.

* 함수 호출과 함수 종료

: 함수 호출 시 실행위치의 이동은 어떻게 이뤄지는가?

: 함수호출이 가능하기 위해서는 pc 레지스터가 순차적인 실행만으로는 부족하고 특정 위치로의 이동이 가능토록 해야만 한다.

: IR을 sp의 fp처럼 사용한다. 이때 과거의 IR값은 스택에 저장한다.

4. 함수 호출 규약

* 함수 호출 규약이란?

: 전달 인자의 스택을 쌓는 방법에 두가지 존재하듯이(위에서 아래로, 아래서 위로), 함수 호출 과정에서 할당된 스택 프레임을 반환하는 방법에도 두가지가 존재한다.

: A함수가 B함수를 호출하는 프로그램을 작성한다고 가정할 때, 스택 프레임을 정리하는 코드가 어디에 존재하느냐에 따라서 그 방법이 크게 두가지로 나뉜다.

: 함수 호출 시 인자를 전달하는 방식과 스택 프레임을 반환하는 방식을 약속해 놓은 것을 함수 호출 규약이라 부른다.

* _cdecl, _stdcall + a

: _stdcall 은 함수 호출 규약을 지정하는 것이다. _stdcall 호출규약에 따라서 STDCallFrunction 함수의 호출과 반환을 처리하라는 뜻

: 모든 함수들은 프로젝트 속성창에 선언된 디폴트 함수 호출 규약을 따르게 되고 따로 선언할 수도 있다.

* 호출 규약의 종류와 의미


: _cdecl은 C/C++의 디폴트 호출 규약으로 알려져 있다.

: _stdcall와 _cdecl의 차이점은 스택 프레임을 반환하는 주체이다. _stdcall은 호출된 함수 내에서 스택 프레임을 반환하도록 정의되어 있다. 

: _fastcall 은 함수를 빠르게 처리하기 위한 호출 규약이다.

: Parameters in registers 부분은 전달되는 인자를 저장할 때 레지스터의 사용 유무를 설명한다. 안의 값은 레지스터 이름을 의미한다.

: 레지스터를 사용한다는 점이 함수 호출을 빨라지게 하는 근거가 된다.

: 64비트에서는 인자를 더 많이 활용하며, windows64bit는 4개 Linux는 최대 14개까지 활용한다.


뇌를 자극하는 윈도우즈 시스템 프로그래밍
국내도서
저자 : 윤성우
출판 : 한빛미디어 2007.03.30
상세보기


+ Recent posts