C++ Builder 2010에서 inline assembly 사용하기
절름발이 프로그래머/Delphi / 2010. 10. 31. 02:24
이전에 Delphi에서 inline assembly를 사용하는 방법에 대해서 글을 하나 썼는데,
C++ Builder에서도 거의 비슷하게 사용할 수 있다는 점을 알아서 그 내용을 정리했다.
Delphi 와는 다른 점이 꽤 있다.
1. 함수 인자값들은 반드시 레지스터에 저장해서 연산하여야 한다. 함수 인자는 바로 연산문에 사용할 수 없다. (지역변수는 변수명으로 바로 사용할 수 있다.)
* 참고: 함수 인자들은 EBP를 기준으로도 접근할 수 있습니다. 함수인자는 앞에서부터 차례로 DWORD PTR [EBP+0Ch], DWORD PTR [EBP+10h], DWORD PTR [EBP+14h] 로 접근 가능합니다.
2. 함수 인자로 주어지는 포인터 변수는 반드시 로컬변수로 재지정해서만 접근하여야 합니다.
3. 함수가 리턴값을 가져야 된다면, 별도로 리턴값을 위한 변수를 지정해서 사용하여야 합니다.
4. 올리디버거에서 추출된 어셈블리 코드안의 숫자값은 모두 16진수 이므로, 인라인 어셈블리 코드로 사용하려면, 모든 숫자값에는 16진수 임을 알리는 “h” 문자를 추가하여야 한다. (MOV EAX, 20 이렇게 되어 있다면, 반드시 MOV EAX, 20h 로 바꾸어야 한다.)
5. 문자열은 주소값으로 연산되므로, 포인터 연산에 주의를 해야한다.(너무나도 당연한 말이다.)
unsigned int TMainForm::keygen1(AnsiString aStr, int aStr_len, int *ret)
{
int ret2;
int *ptr_ret = ret;
asm
{
XOR EDI, EDI // init value := 0
XOR ESI, ESI
XOR EDX, EDX
XOR ECX, ECX // ecx := 0, init value
XOR EBX, EBX // ebx := 0, init value
XOR EAX, EAX
MOV EDX, aStr_len // copy string length
MOV ESI, [aStr] // load string address
MOV EDI, ptr_ret // load integer value address
@@LOOP: // Label
MOVSX EAX, BYTE PTR [ESI+ECX]
INC ECX
XOR EAX, ECX
ADD EBX, EAX
CMP ECX, EDX
JNZ @@LOOP // conditional jump to Label
IMUL EAX, EAX, 6h
MOV DWORD PTR [EDI], EBX // pointer variable value copy
SHL EBX, 7h
MOV ret2, EBX // local variable value copy
ADD EAX, EBX
MOV ret2, EAX // return value
}
return ret2;
}