티스토리 뷰


편견이 깨지는 어셈블리 프로그래밍 - 최적화 강좌 1 - 6  
 
 





어셈블리와 고급 언어의 결합
어셈블리로 만들어진 루틴을 고급 언어와 연결할 수 있는 방법으로는 다음과 같은 방법들이 있다.

인라인 어셈블리
대 부분 저수준을 함께 지원하는 비주얼 C 및 기타 언어에서는 소스 중간에 바로 어셈블리 코드를 삽입시킬 수 있는 인라인 어셈블리라는 기능이 있다. 비주얼 C의 인라인 어셈블리(in-line assambly)는 DB, DW, DD 등의 변수 선언 명령어를 제외한 거의 모든 명령어를 사용할 수 있다. 다름의 간단한 인라인 어셈블리 예제를 보자.

__asm
{
mov ecx , 38
xor eax , eax
Tl_Loop1:
inc eax

loop TL_Loop1
}

사용 방법은 비주얼 C에서 인라인 어셈블리는 함수 안에다가 __asm이라고 적어준 후 어셈블리 명령을 서술해 주면 된다.

__asm mov eax , 80
이와 같이 바로 서술해도 되고 다음과 같이 블럭을 이용해 서술해도 된다, 또한, 인라인 어셈블리에서도 VC++의 변수를 참조하거나 제어할 수 있다.

__asm
{
mov eax , 80
}

다른 연결 방법
앞 에서 소개한 인라인 어셈블리 말고도 다른 연결 방법이 있는데 DLL( Dynamic Linking Library)로 만들어 연결하거나 LIB로 만들어 연결하는 것이다. 이 두 방법은 고급 언어 간에도 자주 사용하는 방법이기도 하고 지면 관계상 넘어가기로 하겠다.

최적화를 위한 기본
우리는 지금까지 몇 가지 CPU의 특성과 어셈블리에 대해서 알아보았다. 이를 바탕으로 몇 가지 최적화를 위한 방법을 정리하면 다음과 같다.

① 분기명령을 최대한 줄인다.
② 명령은 최대한 작은 것으로 선택해 쓴다.
명령들을 잘 보면 개발자가 원하는 방향으로 같은 기능을 가진 명령어들이 여러 개 있는 것을 발견할 수 있을 것이다. 단순히 0인지 아닌지를 비교하기 위해 cmp 명령 대신 or 명령을 썼던 것과 같다.
③ 연산은 되도록 레지스터 내에서 한다.
이 부분은 매우 예민하고도 힘든 부분이다. 메모리에서의 연산은 레지스터에서의 연산보다 느리다. 따라서 레지스터를 적극 활용하는 것을 권장한다. 하지만 계획성 없는 레지스터의 사용으로 인해 코드가 오히려 길어지는 경우가 생긴다. 우리는 이것을 경계해야 한다.
④ 파이프 라인의 룰을 따른다.
많은 생각을 할 부분이다. 파이프 라인의 특성은 CPU마다 약간씩 차이가 있지만 일반적으로 연계된 레지스터나 메모리의 사용이 있는 코드들이 가까이 모여 있지 않고 분산되어 있을수록 파이프 라인과 스캐일러스의 효율이 증가한다.

최 적화란 단원 자체가 만만찮은 영역인지라 이번 호에서는 주로 CPU의 특성과 어셈블리의 고급 기능에 대하여 알아보았다. 다음 호부터는 실질적인 코딩에 들어가도록 하겠다. 아직은 하드웨어 성능이 사용자가 원하는 만큼 충분히 내주지 못하기 때문에 약간의 속도라도 짜내기 위해 노력하는 많은 개발자들을 보았다. 특히 게임이나 멀티미디어 분야에서 이런 노력을 많이 봐 온 필자로서는 작은 경험이나마 이런 독자들에게 도움이 되었으면 하는 바람이다.
다음 호에서는 버스에 대해 간략히 알아보고 데이터에 대한 최적화 부분을 다루겠다. 참고로, 각 연재마다 필자가 속해 있는 프로젝트 팀인 ‘Team BASE’의 사람들이 분담해 원고를 진행할 예정임을 밝혀둔다. 잘못된 부분이나 궁금한 사항은 http://www.ultrasys.co.kr의 잡담 게시판에 남겨주기 바란다(임시로 사용하는 게시판임을 양해 바람).


[ Calling Conventions ]
Calling Conventions란 간단하게 말하면 함수에서 인자를 어떻게 전달하느냐 하는 방식을 나타내는 것이다. <그림 1>에서 보듯이 인자를 전달하는 순서에 따라서 크게 두 가지 방식으로 나뉜다. 어떻게 차이가 나는지 알아보자.


◆ C
C 언어 계열의 컴파일러에서 주로 쓰는 스택 프레임으로써 처음 인자를 맨 마지막 스택프레임에 저장한다. 따라서 첫 번째 인자는 복귀 주소 바로 위에 위치한다(<그림 1>).

◆ StdCall
파스칼 계열의 컴파일러에서 많이 쓰는 스택 프레임으로써 호출에 나타난 순서대로 인자를 전달한다(<그림 2>).


출처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=77