테트리스와 텍스트 뷰어로 어느 정도 FASM으로 어떤 식으로 프로그래밍 해야 하는지 파악한 것 같습니다.
현재 매크로도 어느 정도 구축이 되어 32비트 단위의 데이터를 다룰 경우 직접 어셈블리 명령으로 입력하지 않습니다.
코드만 보면 어셈블리 언어로 보이지 않을 정도 입니다.
사칙연산은 C처럼 *= ++ 등의 연산자로 할 수 있고 윈도우 메세지 처리는 MFC의 메세지 맵과 비슷하지만 더 사용하기 쉽고 단순하게 바꿨습니다.
2차원 배열, 열거자, 문자열 등을 지원하며 배열과 문자열 생성시 크기, 넓이, 높이, 단위 등에 대한 정보가 상수로 자동 생성 되어 따로 크기, 넓이, 등을 계산하는 함수를 호출할 필요가 없습니다.
물론 동적 배열, 문자열에는 해당되지 않습니다.
중요한건 이 기능들을 사용해도 코드의 증가는 전혀 이루어지지 않는다는 겁니다.
고정 크기 배열과 문자열을 사용하거나 어셈블리에 익숙하지 않을 경우 오히려 코드가 감소할 수도 있습니다.
코드가 증가하지 않는 방식으로만 기능을 지원하기 위해 매크로와 옵션에 따른 부분 컴파일로만 기능들을 구현했기 때문입니다.
간단한 프로그램을 만들면서 이런 저런 기능들을 좀 구현하다보니 욕심이 생기기 시작하네요.
코드 증가가 없거나 있어도 아주 적은 수준의 코드 증가만을 허락하면서 상당히 빠른 속도로 개발 가능한 개발환경을 만드는 겁니다.
시간이 많이 걸릴 수 밖에 없는 대작업이 되겠죠.
그런데 생각해보면 FASM 어셈블리 제작자도 한명이고 긴시간을 꾸준이 개발하고 업데이트 해오면서 지금의 FASM이 되었죠.
그래서 틈틈히 개발해볼까 생각중입니다.
아래 코드들이 현재 제 라이브러리를 이용할 경우 윈도우를 생성하기 위한 기본 템플릿입니다.
첫번째가 헤더이고 두번째가 소스입니다.
헤더에 상수로 정의된 값을 바꾸면 자동으로 거기에 맞춰 윈도우를 생성하고 메세지 루프를 돌립니다.
생성전 해야 할 작업은 PreCreateWindow에서 처리하면 됩니다.
Instance, Window handle 등 전역에서 접근 가능해야 하는 최소한의 변수들이 미리 지정되어 있기에 그걸 이용하면 됩니다.
아이콘, 메뉴, 커서 등 메인 윈도우에 연결되는 리소스는 지정된 상수로 리소스 파일에 만들면 자동으로 실행시 로드 됩니다.
지정된 상수에 리소스 파일이 없으면 당연히 해당 코드는 제거되고 컴파일 됩니다.
당연히 직접 프로그래밍 할 때 보다 코드의 증가는 없습니다.
Solid Brush를 사용하지 않으면 컴파일시 해당 코드는 아예 삭제되기 때문이죠.
한마디로 저 아래의 코드들을 순수 어셈블리로 다시 작성해도 같은 기능을 구현하려면 같은 크기의 실행 파일이 만들어 진다는 것이죠.
하여튼 제가 지금까지 테트리스, 뷰어를 만들면서 해왔던 작업이 이겁니다.
테트리스를 이용한 FASM 강의를 하겠다고 하고 하지 못한 이유기도 하구요.
제가 만든 라이브러리를 반영하면서 코드가 계속 변하고 있는 중이고 이후에도 계속 바뀔 가능성이 크기 때문이죠.
; ------------------------------------------------------------------------------
; 일자 2014-12-09
; 목적 전역 변수, 상수 정의
; ------------------------------------------------------------------------------
; 윈도우 스타일
CS_STYLE = CS_HREDRAW + CS_VREDRAW
WS_STYLE = WS_OVERLAPPEDWINDOW
WS_EX_STYLE = 0
; 윈도우 배경색으로 BG_TYPE_COLOR, BG_TYPE_STOCK, BG_TYPE_SOLID 세가지 중 하나를
; 사용한다. BG_TYPE_NULL을 선택하면 배경색을 칠하지 않는다.
MF_BG_TYPE = BG_TYPE_SOLID
MF_BG_COLOR = 00eeeeeeh
_hMFBrush dd MF_BG_COLOR ; 배경색 설정 및 브러시
_sMFClass TSTR 'SDITemplate' ; 윈도우 클래스
_sMFTitle TSTR 'SDI Template' ; 윈도우 타이틀
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; Resource ID
; ------------------------------------------------------------------------------
define IDM_MAINFRAME 101
define IDA_MAINFRAME 102
define IDD_ABOUT 106
define IDM_FILE_EXIT 40000
define IDM_HELP_ABOUT 40001
; ------------------------------------------------------------------------------
; 일자 2014-12-09
; 목적 윈도우 메세지 콜백 함수
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; 윈도우 생성전 윈도우 크기를 계산한다.
; 반환값을 0을 주면 기본 설정으로 윈도우를 생성하고 RECT 구조체 변수 주소를 주면
; 변수에 맞게 윈도우를 생성한다.
; ------------------------------------------------------------------------------
proc PreCreateWindow
Return 0
endp
; ------------------------------------------------------------------------------
; 윈도우 메세지 콜백 함수
; ------------------------------------------------------------------------------
proc WndProc uses ebx edi esi,hWnd, uMessage, wParam, lParam
BEGIN_MESSAGE_MAP
;ON_MESSAGE WM_CREATE, .OnCreate
ON_DESTROY OnDestroy
ON_PAINT OnPaint
ON_SIZE OnSize, OnPaint
ON_ERASEBKGND
ON_MESSAGE WM_KEYDOWN, .OnKeyDown
ON_COMMAND IDM_FILE_EXIT, .OnFileExit
ON_COMMAND IDM_HELP_ABOUT, .OnHelpAbout
END_MESSAGE_MAP
; --------------------------------------------------------------------------
.OnKeyDown:
BEGIN_KEY_MAP
ON_KEY VK_ESCAPE, .OnKeyESC
END_KEY_MAP
; --------------------------------------------------------------------------
; 데이터를 초기화 한다.
; --------------------------------------------------------------------------
;.OnCreate:
; Return 0
; --------------------------------------------------------------------------
.OnFileExit:
SendMessage WM_DESTROY
Return 0
; --------------------------------------------------------------------------
.OnHelpAbout:
ShowAboutDialog
Return 0
; --------------------------------------------------------------------------
; 프로그램을 종료한다.
; --------------------------------------------------------------------------
.OnKeyESC:
SendMessage WM_DESTROY
Return 0
endp
; ------------------------------------------------------------------------------
; 화면을 출력한다.
; ------------------------------------------------------------------------------
proc OnPaint, hWnd, hDC
locals
hBufferHDC dd ?
hOldBitmap dd ?
HDC dd ?
endl
BEGIN_PAINT
; 클라이언트 영역 전체를 색칠한다.
WinCall FillRect, [HDC], _RectClient, [_hMFBrush]
END_PAINT
Return 0
endp
; ------------------------------------------------------------------------------
; 크기 변경시 해야할 일을 한다.
; _RectClient에 윈도우 클라이언트 영역의 크기가 자동으로 저장된다.
; ------------------------------------------------------------------------------
proc OnSize, hWnd, lParam, pFunction
BEGIN_SIZE
END_SIZE
Return 0
endp
; ------------------------------------------------------------------------------
; 사용한 데이터를 운영체제에 돌려주고 종료한다.
; ------------------------------------------------------------------------------
proc OnDestroy, hWnd
END_DESTROY
Return 0
endp