게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
FASM - 5. 'Hello, World!'와 호출 규약
게시물ID : programmer_11170짧은주소 복사하기
작성자 : 중용자
추천 : 8
조회수 : 609회
댓글수 : 0개
등록시간 : 2015/06/12 00:59:35
5.1 FASM 지시어와 명령어만 사용한 Hello, World!

  1. format PE GUI 4.0
  2.  
  3. include 'win32wxp.inc'
  4.  
  5. entry start
  6.  
  7. section '.data' data readable writeable
  8. sCaption    db 'FASM Exam1',0
  9. sText       db 'Hello, Wolrd!',0
  10.  
  11. section '.code' code readable executable
  12. start:
  13.     push 
  14.     push sCaption
  15.     push sText
  16.     push 0
  17.     call [MessageBox]
  18.  
  19.     push 0
  20.     call [ExitProcess]
  21.  
  22. section '.idata' import data readable writeable
  23. library KERNEL32, 'KERNEL32.DLL', \
  24.     USER32, 'USER32.DLL'
  25.  
  26. import  KERNEL32, \
  27.     ExitProcess,'ExitProcess'
  28.  
  29. import  USER32, \
  30.     MessageBox, 'MessageBoxA'

Windows API 함수를 사용하기 위한 정의 부분을 제외하고는 매크로를 사용하지 않은 'Hello, World!' 예제입니다.

- format : 운영체제에 맞는 포맷을 설정합니다. 

운영체제에 따라 MZ- DOS, PE- Win32, PE64- Win64, COFF- Unix, ELF- Linux를 사용합니다.
Unix, Linux, DOS등은 다루지 않을 예정이기 때문에 PE, PE64만 기억하고 있으면 됩니다.
Windows 애플리케이션의 경우 console은 32비트, 64비트 모드 공용으로 사용하고 GUI는 Win32의 경우 GUI 4.0, Win64의 경우 GUI 5.0을 사용합니다.

- entry : 프로그램의 시작점을 설정합니다.

- section : 레지스터 설명 때 나온 세그먼트의 역할을 합니다.

- 13~17 : Windows API MessageBox 함수를 실행합니다.

어셈블러에서 함수 호출시 매개 변수들의 전달은 스택을 이용합니다.
push 명령어로 매개 변수들을 스택에 입력한 후 함수를 호출하는 것이죠.
C로 변환하면 MessageBox(0, sText, sCaption, 64) 가 됩니다.
같은 Windows API 함수인데 어셈블리로 실행할 때와 C로 실행할 떄를 비교해 보면 Paramters의 순서가 역순이죠?
이것은 함수의 호출 규약에 관련된 것인데 분량이 상당한 만큼 분리해서 따로 설명하겠습니다.

- 19~20 : Windows API ExitProcess 함수를 실행합니다.

ExitProcess 함수는 윈도우 프로그램을 종료시키는 함수로 어떤 윈도우 프로그램이던 반드시 ExitProcess 함수로 종료되야 합니다.

- 22~30 : Windows API 함수를 사용하기 위한 정의로 DLL에서 사용하려는 API 함수의 위치를 가져옵니다.


5.2 FASM 매크로, API정의를 사용한 Hello, World!

  1. include 'win32wxp.inc'
  2.  
  3. .data
  4. sCaption    du 'FASM Exam2',0
  5. sText       du 'Hello, Wolrd!',0
  6.  
  7. .code
  8. start:
  9.     invoke MessageBox, 0, sText, sCaption, MB_OK + MB_ICONINFORMATION
  10.     invoke ExitProcess, 0
  11. .end start

위의 긴 코드가 FASM 매크로를 사용하면서 짧게 변경됐습니다.

FASM에서는 12개의 include 파일을 제공합니다.
win32wxp는 32비트 Wide 문자열(유니코드)을 사용하며 x, p는 FASM가 제공하는 확장기능을 사용하겠다는 겁니다.
일반적으로 FASM에서 기본 제공하는 기능을 사용할수록 월등히 프로그래밍이 편해집니다.
유니코드를 사용하는 이유는 Windows 운영체제는 기본적으로 문자열 처리에 유니코드를 이용합니다.
8비트 문자열보다 유니코드 문자열을 사용하는게 향후 다양한 언어를 사용하기에도 편하기 때문에 특별한 이유가 없다면 유니코드를 사용하는 것이 좋습니다.

section 지시어는 .data와 .code 매크로로 대체했습니다.

첫번째 예제에서는 sCaption과 sText의 타입으로 db(Byte)를 사용하였는데 두번째 예제에서 du(WORD)를 사용한 이유는 첫번째 예제의 아래쪽 Windows API 정의를 보면 30줄에 MessageBox, 'MessageBoxA' 라는 부분이 있습니다.
Windows API에서 문자열을 사용하는 API는 대부분 MessageBoxA, MessageBoxW와 같이 2가지 버전이 있습니다.
뒤에 A가 붙은건 ANSI 문자열, W가 붙은건 Wide 문자열 (유니코드)를 지원하는 함수로 첫번째 예제에서는 MessageBox를 MessageBoxA라는 ANSI를 지원하는 API함수로 정의했는데 아래와 같이 정의를 생략할 경우 include에서 불러온 파일에 정의된 API를 사용하는데 win32wxp.inc는 유니코드를 지원하는 Windows API를 정의하고 있습니다.
따라서 sCaption, sText도 유니코드에서 사용할 수 있는 문자열로 정의가 된 것이죠.

push와 call 이용한 Windows API 함수호출은 C에서 호출하는 것과 비슷한 invoke 매크로로 바뀌었습니다.

마지막으로 .end start 매크로가 사용되었는데 .end 매크로를 사용해야 자동으로 Windows API 함수들을 사용할 수 있게 됩니다.


5.3 호출 규약


호출 규약은 함수를 호출하는 방식에 대한 약속입니다.
호출 규약의 종류에는 5가지가 있는데 이 글에서는 자주 사용되는 3가지 호출규약만 설명하겠습니다.

- stdcall

첫번째 예제 MessageBox처럼 인자를 역순으로 push 명령어를 이용하여 스택에 저장하여 전달하고 인자 전달에 사용한 스택의 정리를 호출된 함수에서 하는 호출 규약입니다.
호출자는 역순으로 스택에 인자를 저장한 후 함수를 호출하면 호출된 함수에서 스택에 있는 인자들을 사용한 후 스택에서 인자를 제거한 후 return합니다.
Windows API 함수의 표준 호출 규약입니다.

- cdecl

stdcall 처럼 인자를 역순으로 스택에 저장하고 함수를 호출하나 인자 전달에 사용한 스택의 정리도 함수를 호출한 쪽에서 합니다.
호출자는 역순으로 스택에 인자를 저장하고 함수를 호출한 후 되돌아 오면 스택에서 인자를 제거합니다.
cdecl 호출 규약과 stdcall 호출 규약의 가장 큰 차이점은 cdecl은 printf 같은 함수에서 사용하는 가변 인자를 사용할 수 있다는 겁니다.
Windows API 함수도 wsprintf와 같은 가변 인자를 사용할 수 있는 함수는 cdecl 호출 규약을 사용합니다.

- fastcall

첫번째, 두번째 인자를 ECX, EDX 레지스터로 전달하는 것을 제외하고는 stdcall과 동일한 방식으로 함수를 호출하고 스택을 처리합니다.
인자 2개를 레지스터로 전달하는 만큼 속도가 빠른 장점이 있지만 Intel CPU들에서만 적용되는 규약으로 델파이에서 함수 표준 호출 규약으로 사용하는 것 외에는 거의 사용되지 않습니다.

전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호