::: 개요 :::
본 장에서는 MASM32 패키지의 설치중에 도스창이 열리면서 여러가지 작업을 처리하는 것을 눈여겨본
사용자라면 의아해 할 수 있는 부분에 대한 대답이 될 것이다.
이작업의 대부분은 설치후 MASM32\LIB 에 포함되는 여러가지 라이브러리를 어셈블링하는 작업이다.
(DevX의 경우는 C:\DevX\Lib 이다)
우리는 프로그램에서 Win32API를 사용하기 위해서 해준 작업 있었다. 고수준호출명령인 Invoke를
사용하기 위해서 Include로 INC파일의 경로를 정해주었고(프로토타입), Includelib명령으로 동일한
이름의 라이브러리를 인클루드해준 후 Invoke 함수명 의 형식으로 사용했다.
이상하지 않는가? Win32API의 대부분은 여러가지 .dll에 속해있는데 왜 LIB파일을 사용하는지에 대해서..
프로그래밍중에 자주 나오는 개념중 하나이다. 바로 정적/동적 에 관한 것이다.
라이브러리는 동적라이브러리는 DLL형태로 구성되며, LoadLibrary -> GetProcAddress -> FreeLibrary
의 순서대로 사용하며, 정적라이브러리는 INCLUDELIB형태로 선언해서 사용하는 것이다.
즉, DevX는 Win32API함수를 정적으로 사용하는 것이라는 의미이다. (물론 동적으로 사용할 수 있고,
동적으로 사용하면 사이즈를 획기적으로 줄일 수 있다.! 하지만 이렇게 안해도 충분히! 빠르다 )
이러한 .LIB 파일을 Imported Library라고 부른다. 즉 함수를 사용하기 위해서 어떤 이름으로 호출하며
매개변수는 무엇인지를 알고, 실제 파일에 어디에 있는지를 링커가 알면 자신의 프로그램에 연결시켜서
이용할 수 있기 때문이다. 이것은 비단, 시스템함수에서만 사용하는 것은 아니다.
DevX를 진행하면서 느끼는 점이 있을것이다. 바로 WinMain이 어디서나 유사하다는 것이다. 만약
이것을 정적라이브러리로 구현해놓고 단지 INCLUDELIB Winmain.lib 만 사용하면 되는 것이다.
또는, 기존에 시스템에서 제공하는 여러가지 라이브러리에 자신만의 함수를 추가하거나 제거할 수도
있다는 의미이다. MS사의 Visual C++또한 이러한 DevX에서 사용하는것과 같은 방식을 사용한다.
그래서 DevX의 어셈블리 엔진인 MASM32에서 VisualC++의 라이브러리를 가져와서 사용할 수있는것이다.
::: 임포트 라이브러리란? ::::
DevX와 Visual C++은 아주 간편하면서도 동일한 포맷의 임포트라이브러리를 사용한다. 마이크로소프트의
임포트라이브러리는 COFF포맷형식으로 되어있다. 이것은 OMF형식인 볼랜드의 TASM과는 다르다!
그래서 TASM에서는 DevX의 라이브러리를 호출 할 수가 없다. 여기서 COFF형식을 설명하지는 않는다.
특정, DLL에는 특정함수에 대한 각종 정보가 포함 되어있다. 그중에서도 가장 중요한 정보는 딱 두가지이다.
바로 함수이름과 그함수에서 사용하는 매개변수의 크기이다!!
예를 들어서, kernel32.dll파일을 헥사에디터로 열어보면
__ExitProcess@4
_CreateProcessA@40
등의 문자열을 찾을 수 있을 것이다. 물론 kernel32.lib파일에도 존재한다.
임포트라이브러리에서는 장식문자인 밑줄문자로 시작된다.(C에서 이렇게 함수명에 밑줄을 쓰지말란 얘기를
들어보았는지 모르겠다.. 이유가 있다. 모든것에는....)
저것의 의미는 다음과 같다. Kernel32.dll파일에는 ExitProcess라는 함수가 존재하고 매개변수를 1개
취한다는 의미이다. 32비트 윈도우에서 1개는 4바이트를 의미한다. (DWORD)
CreateProcessA@40은 그럼 무슨의미일까? 40바이트므로 5개(40바이트)를 취한다는 의미이다.
이렇듯, 시스템은 실제 내용은 신경쓰지않고 어떤함수가 매개변수를 얼마를 사용하는지에만 관심있다.
매개변수는 스택을 통해서 운영되는데 이크기를 알아야 정상적으로 시스템이 작동되기 때문이다.
또한가지, MASM의 Invoke 명령은 함수명과 매개변수의 크기만 체크한다는 사실이다. 내용은 상관도
안한다! 시스템에서 제공하는 여러함수이름과 동일하고 동일한 크기의 매개변수만 제공된다면 실제내용을
바꿔서 시스템을 정지시켜버릴 수도 있다는 얘기이다...
::: 임포트라이브러리 생성 :::
예를 들어서 Xeno.dll이라는 파일에서 이러한 임포트 라이브러리를 생성할려면 다음과 같이 한다.
dumpbin.exe (MASM32\Bin) 프로그램을 이용해서 .def파일을 추출할 수 있다. (Module Definition File)
dumpbin.exe /EXPORTS Xeno.dll > Xeno.def
이 명령으로 생성된 모듈선언파일의 내용은 다음과 같이 되어 있다. (예제일뿐이다)
LIBRARY Xeno
EXPORTS
GetUserName
C++이나 델파이 유저들은 이미 눈치 챗을것이다. DLL을 만들때 했던작업이기 때문이다.
이렇게 생성된, Xeno.def 파일을 LIB.EXE 유틸리티로 다시 Xeno.lib 파일로 만들 수 있는 것이다.
LIB.EXE /DEF:Xeno.def
이제, 생성된 Xeno.lib파일을 DevX에서 Invoke 명령으로 사용할 수 있다.
::: 구현 :::
이러한 기본 개념으로 DevX를 이용해서 실제 DLL을 작성해보고 다시 LIB파일로 변환하는 것을 해보자.
함수명과 매개변수의 크기만 정하면 어려운 부분이 전혀 없다! 예제에서는 GetUserName이라는 함수명을
사용하며 매개변수의 크기는 16바이트를 사용한다.
.386
.model flat, stdcall
.code
GetUserName PROC param1:DWORD, param2:DWORD, param3:DWORD, param4:DWORD
GetUserName ENDP
end
이게 끝이다. 이상하지 않는가? 실제 내용이 없다. 위에서 설명했듯이, 내용이 없어도 전혀 관여하지 않는다.
다음으로는 Module Definition File을 (.def)을 생성해야한다.
LIBRARY Xeno.dll
EXPORTS
GetUserName
이제 ml.exe와 link.exe로 실제로 생성해보자.
ml /c /coff /Cp Xeno.asm
link /dll /noentry /def:xeno.def /subsystem:windows xeno.obj
이렇게 Invoke로 호출가능한 임포트 라이브러리가 생성되었다!!
Xeno.dll Xeno.Asm Xeno.exp Xeno.lib Xeno.obj 파일이 생성되었을 것이다.
::: 마치며 :::
어찌보면 이것이 강좌인가 싶지만, 어느정도 익혀졌을때는 라이브러리(정적/동적)를 직접 다루고
싶어질때가 있을 것이다. 시스템에서 수많은 기능을 제공하는데 이기능을 변경하거나 자기만의
함수로 넣어서 사용할 수도 있게되는 강력한 것이다. OOP에서도 이와 유사한 방식을 사용하지만,
어셈블리나 API환경에서는 OOP따위 몰라도 된다. 모든것은 기계어로 변경되어지고 단지 설계자가
이해하기 쉽도록 OOP가 적용된 것일뿐, 어셈블리언 입장에서보면 그냥.........
본 장에서는 MASM32 패키지의 설치중에 도스창이 열리면서 여러가지 작업을 처리하는 것을 눈여겨본
사용자라면 의아해 할 수 있는 부분에 대한 대답이 될 것이다.
이작업의 대부분은 설치후 MASM32\LIB 에 포함되는 여러가지 라이브러리를 어셈블링하는 작업이다.
(DevX의 경우는 C:\DevX\Lib 이다)
우리는 프로그램에서 Win32API를 사용하기 위해서 해준 작업 있었다. 고수준호출명령인 Invoke를
사용하기 위해서 Include로 INC파일의 경로를 정해주었고(프로토타입), Includelib명령으로 동일한
이름의 라이브러리를 인클루드해준 후 Invoke 함수명 의 형식으로 사용했다.
이상하지 않는가? Win32API의 대부분은 여러가지 .dll에 속해있는데 왜 LIB파일을 사용하는지에 대해서..
프로그래밍중에 자주 나오는 개념중 하나이다. 바로 정적/동적 에 관한 것이다.
라이브러리는 동적라이브러리는 DLL형태로 구성되며, LoadLibrary -> GetProcAddress -> FreeLibrary
의 순서대로 사용하며, 정적라이브러리는 INCLUDELIB형태로 선언해서 사용하는 것이다.
즉, DevX는 Win32API함수를 정적으로 사용하는 것이라는 의미이다. (물론 동적으로 사용할 수 있고,
동적으로 사용하면 사이즈를 획기적으로 줄일 수 있다.! 하지만 이렇게 안해도 충분히! 빠르다 )
이러한 .LIB 파일을 Imported Library라고 부른다. 즉 함수를 사용하기 위해서 어떤 이름으로 호출하며
매개변수는 무엇인지를 알고, 실제 파일에 어디에 있는지를 링커가 알면 자신의 프로그램에 연결시켜서
이용할 수 있기 때문이다. 이것은 비단, 시스템함수에서만 사용하는 것은 아니다.
DevX를 진행하면서 느끼는 점이 있을것이다. 바로 WinMain이 어디서나 유사하다는 것이다. 만약
이것을 정적라이브러리로 구현해놓고 단지 INCLUDELIB Winmain.lib 만 사용하면 되는 것이다.
또는, 기존에 시스템에서 제공하는 여러가지 라이브러리에 자신만의 함수를 추가하거나 제거할 수도
있다는 의미이다. MS사의 Visual C++또한 이러한 DevX에서 사용하는것과 같은 방식을 사용한다.
그래서 DevX의 어셈블리 엔진인 MASM32에서 VisualC++의 라이브러리를 가져와서 사용할 수있는것이다.
::: 임포트 라이브러리란? ::::
DevX와 Visual C++은 아주 간편하면서도 동일한 포맷의 임포트라이브러리를 사용한다. 마이크로소프트의
임포트라이브러리는 COFF포맷형식으로 되어있다. 이것은 OMF형식인 볼랜드의 TASM과는 다르다!
그래서 TASM에서는 DevX의 라이브러리를 호출 할 수가 없다. 여기서 COFF형식을 설명하지는 않는다.
특정, DLL에는 특정함수에 대한 각종 정보가 포함 되어있다. 그중에서도 가장 중요한 정보는 딱 두가지이다.
바로 함수이름과 그함수에서 사용하는 매개변수의 크기이다!!
예를 들어서, kernel32.dll파일을 헥사에디터로 열어보면
__ExitProcess@4
_CreateProcessA@40
등의 문자열을 찾을 수 있을 것이다. 물론 kernel32.lib파일에도 존재한다.
임포트라이브러리에서는 장식문자인 밑줄문자로 시작된다.(C에서 이렇게 함수명에 밑줄을 쓰지말란 얘기를
들어보았는지 모르겠다.. 이유가 있다. 모든것에는....)
저것의 의미는 다음과 같다. Kernel32.dll파일에는 ExitProcess라는 함수가 존재하고 매개변수를 1개
취한다는 의미이다. 32비트 윈도우에서 1개는 4바이트를 의미한다. (DWORD)
CreateProcessA@40은 그럼 무슨의미일까? 40바이트므로 5개(40바이트)를 취한다는 의미이다.
이렇듯, 시스템은 실제 내용은 신경쓰지않고 어떤함수가 매개변수를 얼마를 사용하는지에만 관심있다.
매개변수는 스택을 통해서 운영되는데 이크기를 알아야 정상적으로 시스템이 작동되기 때문이다.
또한가지, MASM의 Invoke 명령은 함수명과 매개변수의 크기만 체크한다는 사실이다. 내용은 상관도
안한다! 시스템에서 제공하는 여러함수이름과 동일하고 동일한 크기의 매개변수만 제공된다면 실제내용을
바꿔서 시스템을 정지시켜버릴 수도 있다는 얘기이다...
::: 임포트라이브러리 생성 :::
예를 들어서 Xeno.dll이라는 파일에서 이러한 임포트 라이브러리를 생성할려면 다음과 같이 한다.
dumpbin.exe (MASM32\Bin) 프로그램을 이용해서 .def파일을 추출할 수 있다. (Module Definition File)
dumpbin.exe /EXPORTS Xeno.dll > Xeno.def
이 명령으로 생성된 모듈선언파일의 내용은 다음과 같이 되어 있다. (예제일뿐이다)
LIBRARY Xeno
EXPORTS
GetUserName
C++이나 델파이 유저들은 이미 눈치 챗을것이다. DLL을 만들때 했던작업이기 때문이다.
이렇게 생성된, Xeno.def 파일을 LIB.EXE 유틸리티로 다시 Xeno.lib 파일로 만들 수 있는 것이다.
LIB.EXE /DEF:Xeno.def
이제, 생성된 Xeno.lib파일을 DevX에서 Invoke 명령으로 사용할 수 있다.
::: 구현 :::
이러한 기본 개념으로 DevX를 이용해서 실제 DLL을 작성해보고 다시 LIB파일로 변환하는 것을 해보자.
함수명과 매개변수의 크기만 정하면 어려운 부분이 전혀 없다! 예제에서는 GetUserName이라는 함수명을
사용하며 매개변수의 크기는 16바이트를 사용한다.
.386
.model flat, stdcall
.code
GetUserName PROC param1:DWORD, param2:DWORD, param3:DWORD, param4:DWORD
GetUserName ENDP
end
이게 끝이다. 이상하지 않는가? 실제 내용이 없다. 위에서 설명했듯이, 내용이 없어도 전혀 관여하지 않는다.
다음으로는 Module Definition File을 (.def)을 생성해야한다.
LIBRARY Xeno.dll
EXPORTS
GetUserName
이제 ml.exe와 link.exe로 실제로 생성해보자.
ml /c /coff /Cp Xeno.asm
link /dll /noentry /def:xeno.def /subsystem:windows xeno.obj
이렇게 Invoke로 호출가능한 임포트 라이브러리가 생성되었다!!
Xeno.dll Xeno.Asm Xeno.exp Xeno.lib Xeno.obj 파일이 생성되었을 것이다.
::: 마치며 :::
어찌보면 이것이 강좌인가 싶지만, 어느정도 익혀졌을때는 라이브러리(정적/동적)를 직접 다루고
싶어질때가 있을 것이다. 시스템에서 수많은 기능을 제공하는데 이기능을 변경하거나 자기만의
함수로 넣어서 사용할 수도 있게되는 강력한 것이다. OOP에서도 이와 유사한 방식을 사용하지만,
어셈블리나 API환경에서는 OOP따위 몰라도 된다. 모든것은 기계어로 변경되어지고 단지 설계자가
이해하기 쉽도록 OOP가 적용된 것일뿐, 어셈블리언 입장에서보면 그냥.........