2011년6월22일_NASM으로 어셈블한 프로시저를 C Code에서 호출

 

 

NASM Download

 

NASM어셈블러를 다운받기 위해 http://www.nasm.us 에 접속하여…

image

상단 4번째 메뉴 Download를 클릭한다.

 

image

nasm 2.10rc6가 최신판이나 그 보다 한 단계 낮은 rc5(안정화된 것)을 받아야 하니 링크를 클릭한다.

 

image

우리는 windows플랫폼에서 Code를 작성하고 컴파일할 것이므로 windows용을 받으러…
win32폴더를 더블클릭한다.

 

image

압축된 형태의 파일인 zip파일을 다운 받아야 하니 링크를 클릭하자..

 


image

압축을 풀면 nasm.exe파일이 보인다.
이 파일을 복사하여 C:\Program Files\Microsoft Visual Studio\VC98\Bin 폴더에 붙여넣자.

 

image

복사가 제대로 되었는지 확인하자.
이 폴더는 환경변수 path에 등록이 되어 있으므로 nasm.exe파일이 없는 어느 디렉토리에서도 실행이 가능하다.

어셈블러 세팅은 끝났으니 관련 문서를 다운받자.


image

다시 http://www.nasm.us 에 접속하여,
7번째 메뉴인 문서를 클릭하자.

image

지금 공부하고 있는 책은 rc4버전이나 홈페이지에는 없으므로 rc6를 받는다.
확인해보니 p.108는 똑같았다. (실습에 사용될 코드)
나머지는 글을 쓸 때 확인해서 다른 점을 적겠다.


 

nasm으로 어셈블하고 그 프로시저를 C Code에서 호출

 


image

실습에 사용할 어셈블리어 코드는 nasmdoc.pdf파일의 108페이지에 있는 myfunc프로시저가 있는 코드이다.
밑에 printf는 하지 않는다.


image

문서의 소스코드를 상기와 같이 바꾼다.
segment .text는 코드영역의 시작이라는 것을 알려주고, text와 code는 같은 뜻이다.
global은 MASM의 PUBLIC과 같은 뜻인 것 같다.

프로시저명 앞에 언더바는 윈도우 cl (비주얼스튜디오 6.0)로 컴파일할 경우에 꼭 붙여줘야 하고,
                                리눅스 gcc로 컴파일할 경우엔 빼야한다.

_myfunc: 은 라벨명이고 실제 실행코드는 아니다.
global이 프로시저의 시작을 나타내는 건지 잘 알 수 없으나 들여쓰기를 한 번 더 해야 할 것만 같다.

entry code(인입코드)는 그대로 두고 sub esp, 0x40 줄을 지운다음에,
프로시저의 리턴값을 바로 넣어주기 위해 mov ebx, …을 mov eax, [ebp + 8]로 바꾼다.
[ebp + 8]은 현재 stack을 가리키는 곳이 예전 함수..즉, 호출함수의 ebp의 주소가 담겨 있는 곳이고,
               그 곳에서 +8이니 2칸 내려간다는 뜻이다.
               그러니 복귀주소를 지나 첫 인자가 위치한 곳이 되는 것이다. (첫 인자를 마지막에 넣는다.)
다음 줄에는,

inc eax

를 삽입하는데 이 명령어의 뜻은 eax의 값을 1증가시킨다는 것이다.

leave는 말 그대로 떠나다는 뜻이고, ret는 함수 종료전에 꼭 있는 명령어로 호출한 함수로 돌아가는 절차…
① stack영역에 있는 복귀주소를 eip레지스터에 넣는다.
② esp의 값을 4증가 시킨다. (한 칸 내린다.)

를 수행한다.

myfunc프로시저를 호출할 C Code는 아래와 같다.

   1:  //myfunc.asm파일의 함수호출
   2:  #include <stdio.h>
   3:   
   4:  int myfunc(int);
   5:   
   6:  int main()
   7:  {
   8:      int iNumber;
   9:      
  10:      iNumber = myfunc(2147483647);
  11:      
  12:      printf("%d\n", iNumber);
  13:   
  14:      return 0;
  15:  }

myfunc을 호출할 때 인자값으로 int형 4Bytes이 최대값인 2^31 - 1인 2147483647을 넣는다.
그럼 최대값보다 1이 큰 수는 int형 정수의 최소값이 된다.

 

image

nasm –f 파일포맷 소스파일명.asm

이런 형식으로,

> nasm –f coff myfunc.asm

명령으로 myfunc.o 오브젝트 파일을 생성하자.

 

image

> cl main.c myfunc.o

명령으로 main.c를 컴파일하여 myfunc.o파일을 링크하자.

그런데 실습할 때 뜨지 않던 오류가 보고서를 쓰려니 뜬다.
unrecognized source file type myfunc.o object file assumed (알 수없는 소스 파일 형식 myfunc.o 개체 파일은 가정)
구글번역기로 돌려 보니 더욱 더 모르겠다.

그래도 아래와 같이 실행이 되니 참 이상하다. 경고라서 그런가…

image

 

iNumber = myfunc(100);

C Code 10번째 줄의 호출시 인자값을 100으로 바꾸고 다시 컴파일하여 실행해보면,

image

결과는 항상 인자로 넘겨준 값에서 1증가한 값이 출력된다는 것을 알 수 있다.