|
CS/Common 2011. 5. 25. 14:19
원문 : Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3A
권한 레벨은 세그먼트 디스크립터의 세그먼트 셀렉터가 세그먼트 레지스터로 로드될 때 체크된다.
CPL (Current Privilege Level)
: 현재 실행되고 있는 태스크의 특권 레벨로, CS, SS 세그먼트 레지스터 0, 1 번째 비트.
: 일반적으로 CPL은 명령어가 페치되는 코드 세그먼트의 특권 레벨과 동일하다.
: 프로세서는 프로그램 컨트롤이 다른 권한 레벨을 가진 코드 세그먼트로 전이될 때 CPL을 변경한다.
: CPL은 conforming 코드 세그먼트에 접근할 때 약간 다르게 취급된다. Confirming 코드 세그먼트는 confirming 코드의 DPL보다 같거나 더 작은 권한(숫자적으로 높은)을 가진 어떤 다른 권한 레벨에서 접근될 수 있다.
: CPL은 프로세서가 CPL과 다른 권한 레벨을 가진 conforming 코드 세그먼트에 접근할 때 변경되지 않는다.
DPL (Descriptor Privilege Level)
: 세그먼트나 게이트 디스크립터가 포함하고 있는 필드.
: 세그먼트나 게이트의 특권레벨.
: 현재 실행되고 있는 코드가 세그먼트나 게이트에 접근하려고 할 때, 세그먼트나 게이트의 DPL은 CPL과 세그먼트가 게이트의 RPL과 비교된다.
: DPL은 세그먼트나 게이트가 엑세스되고 있는 타입에 따라 다르게 해석된다.
- Data segment - DPL은 프로그램이나 태스크가 세그먼트에 엑세스를 허용해야만 하는 가장 낮은 권한 레벨(숫자상으로 가장 높은)을 가리킨다. 예를 들어, 만약 데이터 세그먼트의 DPL이 1이라면, 0이나 1의 CPL에서 동작하고 있는 프로그램만이 세그먼트에 엑세스 할 수 있다.
- Nonconforming code segment (without using call gate) - DPL은 프로그램이나 태스크가 세그먼트에 엑세스하기 위해 가져야 하는 권한 레벨을 가리킨다. 예를 들어 만약 nonconforming 코드 세그먼트의 DPL이 0이라면 CPL 0에서 수행되는 프로그램만이 이 세그먼트에 엑세스 할 수 있다.
- Call gate - DPL은 현재 수행되고 있는 프로그램이나 태스크가 될 수 있고 여전히 콜 게이트에 접근할 수 있는 가장 낮은 레벨(숫자상으로 가장 높은)을 가리킨다. (data segment와 같은 규칙)
- Conforming code segment and nonconforming code segment accessed through a call gate - DPL은 프로그램이나 태스크가 세그먼트에 엑세스를 허용해야만 하는 가장 높은 레벨(숫자상으로 가장 낮은)을 가리킨다. 예를 들어, 만약 conforming 코드 세그먼트의 DPL이 2 이고, 프로그램이 0이나 1의 CPL에서 동작하고 있다면 세그먼트에 엑세스 할 수 없다.
- TSS - DPL은 현재 실행되고 있는 프로그램이나 태스크가 될 수 있거나 여전히 TSS에 접근 할 수 있는 가장 낮은 권한 레벨(숫자상으로 가장 높은)을 가리킨다. (data segment와 같은 규칙)
RPL (Requested Privilege Level)
: 세그먼트 셀렉터의 0, 1 번째 비트.
: 세그먼트 셀렉터에 할당된 override된 권한 레벨이다.
: 프로세서는 세그먼트의 접근이 허용되는지 판단하기 위해 CPL과 함께 RPL을 체크한다.
: 비록 세그먼트의 접근을 요청하는 프로그램이나 태스크가 세그먼트에 접근하기 위한 충분한 권한을 가지고 있더라도, 만약 RPL이 충분한 권한 레벨을 가지고 있지 않다면, 접근은 거부된다. 즉, 세그먼트 셀렉터의 RPL이 CPL보다 낮은 권한 레벨(숫자상으로 높은)인 경우, RPL은 CPL을 override 한다. (반대도 마찬가지이다.)
: 5.10.4 Checking Caller Access Privileges (ARPL Instruction) 참고
: RPL은 만약 프로그램 자체가 세그먼트에 대한 엑세스 권한을 가지고 있지 않다면 에플리케이션 프로그램 대신에 권한 코드(privileged code)가 세그먼트에 접근하지 않는 것을 보장하기 위해 사용된다.
발번역 주의. 이놈의 영어... ㅜㅜ
CS/Common 2010. 1. 20. 10:45
원문 : Wiki
In compiler theory, copy propagation is the process of replacing the occurrences of targets of direct assignments with their values. A direct assignment is an instruction of the form y = x, which simply assigns the value of x to y.
From the following code:
y = xz = 3 + y
Copy propagation would yield:
z = 3 + x
Copy propagation often makes use of reaching definitions, use-def chains and def-use chains when computing which occurrences of the target may be safely replaced. If all upwards exposed uses of the target may be safely modified, the assignment operation may be eliminated.
Copy propagation is a useful "clean up" optimization frequently used after other optimizations have already been run. Some optimizations require that copy propagation be run afterward in order to achieve an increase in efficiency.
CS/Common 2010. 1. 8. 07:10
원문 : Stanford iTunesU Programming Paradigm 17강
int DownloadSingleFile(const char* server, const char* path);
int DownloadAllFiles(const char* server, const char* files[], int n)
{
int totalBytes = 0;
Semaphore lock = 1;
Semaphore childrenDone = 0;
for (int i=0; i < n; ++i)
{
ThreadNew("DownloadSingleFile", DownloadSingleFile, 4, server, files[i], &
totalBytes, lock, childrenDone);
}
for (int i=0; i < n; ++i)
{
// wait return.
SemaphoreWait(childrenDone);
}
return totalBytes;
}
void DownloadHelper(const char* server, const char* path,
int* returnButes, Semaphore lock, Semaphore parentToSignal)
{
int bytesDownloaded = DownloadSingleFile(server, path);
SemaphoreWait(lock);
*numBytes += bytesDownloaded;
SemaphoreSignal(lock);
SemaphoreSignal(parentToSignal);
}
CS/Common 2010. 1. 8. 06:48
원문 : Stanford iTunesU Programming Paradigm 17강
Semaphore forks[5] = {1, 1, 1, 1, 1}
Semaphore numAllowedToEat(4); // 최소한 한명은 Idle. DeadLock 피함.
void Philosopher(int id)
{
for (int i=0; i < 3; ++i)
{
Think();
SemaphoreWait( numAllowedToEat );
SemaphoreWait( forks[ id ] );
SemaphoreWait( forks[ (i+1)%5 ] );
Eat();
SemaphoreSignal( forks[ id ] );
SemaphoreSignal( forks[ (id+1)%5 ] );
SemaphoreSignal( numAllowedToEat );
}
}
학부때 OS 시간에는 뭔가 엄청 복잡하고 어려웠는데... 왜이렇게 간단하지...? ;;;
CS/Common 2010. 1. 8. 05:45
원문 : Stanford iTunesU Programming Paradigm 16강
버퍼에서 Read 전에 Write 금지.
Write 되지 않은 버퍼 Read 하지 않기.
char buffer[8];
Semaphore emptyBuffers(8);
Semaphore fullBuffers(0);
int main()
{
ThreadNew("Writer", Writer, 0);
ThreadNew("Reader", Reader, 0);
RunAllThread();
}
void Writer()
{
for (int i=0; i < 40; ++i)
{
char c = PrepareRandomChar();
SemaphoreWait(emptyBuffers);
buffer[ i%f ] = c;
SemaphoreSignal(fullBuffers);
}
}
void Reader()
{
for (int i=0; i < 40; ++i)
{
SemaphoreWait(fullBuffers);
char c = buffer[ i%f ];
ProcessChar(c);
SemaphoreSignal(emptyBuffers);
}
}
CS/Common 2009. 9. 11. 15:53
Google 친구 아저씨들이 짠 코드를 보면 가끔 이런 형식이 보인다.
do
{
result = false;
...
if ( result = foo() )
break;
...
if ( result = bar() )
break;
...
} while (0);
if (false == result)
{
...
}
foo()나 bar()에서 실패시 이후의 코드를 처리하지 않기 위함인데,
결국은 리눅스 커널의 네트워크 관련 코드의 다음과 같은 일을 한다.
if ( result = foo() )
goto FAILED;
...
if ( result = basr() )
goto FAILED;
...
FAILED :
...
결국 goto를 사용하지 않고, do-while(0) 을 이용하여 break를 사용해서 분기를 제어한 것인데,
나는 커널 코드에 익숙해져 있어서 인지, goto가 더 명시적이고 좋아 보인다.
또한 do-while(0)과 break를 이용한 방법은 그 안에 loop가 없는 경우만 사용할 수 있는 단점도 있다.
하지만,
if ( )
{
if ( )
{
if ( )
{
if ( )
{
...
}
}
}
}
요렇게 된 코드를
do {
if (! )
{
break;
}
if (! )
{
break;
}
if (! )
{
break;
}
if (! )
{
break;
}
} while(0);
요렇게 쓸 수 있다는 점에서는 참 매력적인 방법이다.
첨에 이 코드를 봤을때는 그냥 그렇구나 하고 지나갔었다.
그런데 우연히 미팅 시간에 팀원들과 이 코드에 대해서 얘기를 하게 되었는데, 사람들이 좋은 방법이다... 라고 대부분 얘기 하길래 포스팅 까지... 역시 셀로판귀... 팔락팔락... orz
CS/Common 2009. 9. 11. 13:08
CS/Common 2009. 4. 10. 22:02
. 모든 calling convention에서 모든 Arguments는 함수로 전달될 32비트로 확장되며 리턴 값 또한 32비트로 확장되며, EAX에 리턴된다. 단, 8-byte 구조체에 대해서는 EDX:EAX 레지스터 쌍에 리턴된다.
. 더 큰 구조체는 리턴 구조체를 숨기기 위해서 EAX레지스터에 포인터로서 리턴된다.
. Parameter는 스택에 오른쪽에서 왼쪽으로 push 된다.
(Structures that are not PODs will not be returned in registers.)
.만약 ESI, EDI, EBX, EBP 레지스터가 함수 내부에서 사용된다면, 컴파일러는 이들을 restore하고 save하기 위해서 prolog와 epilog 코드를 생성한다.
__cdecl
Stack Cleanup : Caller
인자 전달 : 스택에 Parameters를 reverse order로 Push한다. (RIGHT to LEFT)
C/C++ 에서의 기본 Calling convention이다.
스택이 Caller에 의해서 cleanup 되기 때문에 가변인자 함수를 사용할 수 있다.
각 함수를 호출할 때마다 cleanup 코드를 포함하애 하기 때문에 __stdcall보다 큰 실행 파일을 생성한다.
__cdecl 변경자는 함수 이름이나 variable 전에 위치시킨다.
__cdecl을 강제하기 위해서는 /Gd 컴파일러 옵션을 지정한다.
/Gz(stdcall), /Gr(fastcall) 컴파일러 옵션을 지정했을 경우만 __cdecl을 필요로 한다.
// Example of the __cdecl keyword on function
int __cdecl system(const char *);
// Example of the __cdecl keyword on function pointer
typedef BOOL (__cdecl *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);
|
foo(1, 2, 3, 4);
004118F3 push 4
004118F5 push 3
004118F7 push 2
004118F9 push 1
004118FB call foo (411118h)
00411900 add esp,10h
int __cdecl foo(int a, int b, int c, int d) {
00411840 push ebp
00411841 mov ebp,esp
00411843 sub esp,0CCh
00411849 push ebx
0041184A push esi
0041184B push edi
0041184C lea edi,[ebp-0CCh]
00411852 mov ecx,33h
00411857 mov eax,0CCCCCCCCh
0041185C rep stos dword ptr es:[edi]
int x = a+b+c+d;
0041185E mov eax,dword ptr [a]
00411861 add eax,dword ptr [b]
00411864 add eax,dword ptr [c]
00411867 add eax,dword ptr [d]
0041186A mov dword ptr [x],eax
return x;
0041186D mov eax,dword ptr [x]
00411870 pop edi
00411871 pop esi
00411872 pop ebx
00411873 mov esp,ebp
00411875 pop ebp
00411876 ret
}
|
__stdcall
Stack Cleanup : Callee
인자 전달 : 스택에 Parameters를 reverse order로 Push한다.(RIGHT TO LEFT)
Win32 API를 호출하기 위해 사용된다.
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
__stdcall을 강제하기 위해서는 /Gz 컴파일러 옵션을 지정한다.
__cdecl로 선언된 함수와 같은 방법으로 values를 리턴한다.
// Example of the __stdcall keyword
#define WINAPI __stdcall
// Example of the __stdcall keyword on function pointer
typedef BOOL (__stdcall *funcname_ptr)
(void * arg1, const char * arg2, DWORD flags, ...);
|
foo(1, 2, 3, 4);
004118F3 push 4
004118F5 push 3
004118F7 push 2
004118F9 push 1
004118FB call foo (411249h)
int __stdcall foo(int a, int b, int c, int d) {
00411840 push ebp
00411841 mov ebp,esp
00411843 sub esp,0CCh
00411849 push ebx
0041184A push esi
0041184B push edi
0041184C lea edi,[ebp-0CCh]
00411852 mov ecx,33h
00411857 mov eax,0CCCCCCCCh
0041185C rep stos dword ptr es:[edi]
int x = a+b+c+d;
0041185E mov eax,dword ptr [a]
00411861 add eax,dword ptr [b]
00411864 add eax,dword ptr [c]
00411867 add eax,dword ptr [d]
0041186A mov dword ptr [x],eax
return x;
0041186D mov eax,dword ptr [x]
00411870 pop edi
00411871 pop esi
00411872 pop ebx
00411873 mov esp,ebp
00411875 pop ebp
00411876 ret 10h
}
|
__fastcall
Stack Cleanup : Callee
인자 전달 : Stored in registers, then pushed on stack
가능하다면 arguments가 함수에 레지스터를 통하여 전달된다.
이후의 컴파일러는 parameters를 저장하기 위해 다른 register를 사용할 수도 있다.
__fastcall을 강제하기 위해서는 /Gr 컴파일러 옵션을 지정한다.
// Example of the __fastcall keyword
#define FASTCALL __fastcall
void FASTCALL DeleteAggrWrapper(void* pWrapper);
// Example of the __ fastcall keyword on function pointer
typedef BOOL (__fastcall *funcname_ptr)
(void * arg1, const char * arg2, DWORD flags, ...);
|
foo(1, 2, 3, 4);
004118F3 push 4
004118F5 push 3
004118F7 mov edx,2
004118FC mov ecx,1
00411901 call foo (41124Eh)
int __fastcall foo(int a, int b, int c, int d) {
004115D0 push ebp
004115D1 mov ebp,esp
004115D3 sub esp,0E4h
004115D9 push ebx
004115DA push esi
004115DB push edi
004115DC push ecx
004115DD lea edi,[ebp-0E4h]
004115E3 mov ecx,39h
004115E8 mov eax,0CCCCCCCCh
004115ED rep stos dword ptr es:[edi]
004115EF pop ecx
004115F0 mov dword ptr [ebp-14h],edx
004115F3 mov dword ptr [ebp-8],ecx
int x = a+b+c+d;
004115F6 mov eax,dword ptr [a]
004115F9 add eax,dword ptr [b]
004115FC add eax,dword ptr [c]
004115FF add eax,dword ptr [d]
00411602 mov dword ptr [x],eax
return x;
00411605 mov eax,dword ptr [x]
00411608 pop edi
00411609 pop esi
0041160A pop ebx
0041160B mov esp,ebp
0041160D pop ebp
0041160E ret 8
}
|
__thiscall
Stack Cleanup : Callee
인자 전달 : Pushed on stack; this pointer stored in ECX
__clrcall
Stack Cleanup : n/a
인자 전달 : Parameters를 CLR expression stacke에 order로 Load한다.(left to right).
예전에 사용하던 블로그에 있던 글인데, 정리할 겸 다시 정리했다. 이놈의 calling convention은 왜 자꾸 까먹는건지.. ㅜㅜ
출처 : MSDN, 나의 옛 블로그
|