외로운 Nova의 작업실

Assembly 언어 공부 - 19(라이브러리 프로시저 설명) 본문

Programming/Assembly

Assembly 언어 공부 - 19(라이브러리 프로시저 설명)

Nova_ 2022. 8. 18. 17:55

안녕하세요, 이번 시간에는 irvine16과 irvine32 라이브러리에 있는 프로시저가 어떻게 사용되는지 알아보도록 하겠습니다.

 

CloseFile

CloseFile 프로시저는 이전에 생성하거나 열었던 파일을 닫습니다. 파일은 eax에 들어있는 32비트 정수 핸들로 식별됩니다. 파일이 성공적으로 닫히면 eax로 반환되는 값은 0이아닌 값입니다. 아래는 예시입니다.

mov eax, filehandle
call CloseFile

 

Clrscr

Clrscr 프로시저는 콘솔 윈도우를 깨끗하게 지웁니다. 이 프로시저는 일반적으로 프로그램의 시작과 끝에서 호출됩니다. 프로그램의 중간에서 호출된다면 사용자가 화면을 지우기전에 스크린에 이미있던 정보를 볼 수 있게 WaitMsg 프로시저를 호출하는 것을 추천합니다. 아래는 예시입니다.

call WaitMsg	;"press any key...."
call Clrscr

 

CreateOutputFile

CreateOutputFile 프로시저는 새 디스크 파일을 생성하고 출력 모드로 엽니다. 프로시저를 호출할때는 파일 이름의 오프셋을 EDX로 넘겨주고, 프로시저는 EDX를 참고합니다. 파일이 성공적으로 생성되었다면 EAX는 유효한 파일 핸들(32비트 정수)를 가집니다. 그렇지 않으면 EAX는 INVALID_HANDLE_VALUE가 됩니다. 아래는 예시입니다.

.data
filename BYTE "testfile.txt". 0
.code
mov edx, offset filename
call CreateOutputFile

 

Crlf

Crlf 프로시저는 콘솔 윈도우에서 커서를 다음 줄의 시작으로 나아가게합니다. 즉, ASCII 코드의 0Dh와 0Ah값으로 구성되는 문자열을 출력합니다. 아래는 예시입니다.

call Crlf

 

Delay

Delay 프로시저는 지정된 msec 단위의 시간동안 프로그램을 멈추게합니다. EAX를 시간으로 참조합니다. 아래는 예시입니다.

mov eax, 1000
call Delay

 

DumpMem

DumpMem 프로시저는 일정 범위 위치의 메모리를 콘솔 윈도우에 16진수로 출력합니다. 메모리의 시작주소를 ESI로, 출력 단위 크기를 EBX로, 출력 단위 갯수를 ECX로 전달합니다. 다음예는 9개의 워드 배열을 16진수로 출력합니다.

.data
araay WORD 1, 2, 3, 4, 5, 6, 7, 8, 9
.code
main PROC
    mov esi, OFFSET array
    mov ecx, LENGTHOF array
    mov ebx, TYPE array
    call DumpMem

출력은 0001 0002 0003 0004 0005 0006 0007 0008 0009 가 됩니다.

 

DumpRegs

DumpRegs 프로시저는 EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP 와 EFL 레즈스터를 16진수로 출력합니다. 또한, CF, SF, ZF, OF, AAF, PF 플래그 값도 출력합니다. 다음은 예시입니다.

call DumpRegs

 

GetCommandTail

GetCommandTail 프로시저는 프로그램의 명령어 행을 문자열로 복사합니다. 명렁어 행이 비어있으면 Carry 플래그는 1이 되며 그렇지 않으면 0이 됩니다. 이 프로시저는 명령어 행에서 매개변수를 넘겨줄 수 있도록 할때 유용합니다. 예시로 Encrypt 라는 프로그램이 file1.txt를 읽어서 file2.txt라는 출력파일을 생성한다고 할때, 명령 프롬프트에서는 아래와 같이 사용합니다.

Encrypt file1.txt file2.txt

그러면 Encrypt 프로그램의 첫번째 코드는 명령어 인수를 문자열로 받아 ffile1.txt라는 문자열의 이름을 가진 파일을 열고, file2.txt라는 문자열의 이름을 가진 텍스트 파일을 생성해야합니다. 즉, 인수를 문자열로 받아야한다는 거죠. 그래서 Encrypt프로그램의 첫번째 코드는 아래와 같을 것 입니다. 단, GetCommandTail 명령어를 호출할때는 문자열을 담을 129바이트 이상의 크기를 갖는 배열의 오프셋을 EDX에 넣어줘야합니다.

.data
cmdTail BYTE 129 DUP(0)
.code
mov edx, OFFSET cmdTail
call GetCommanTail

위 코드가 실행되면 "file1.txt file2.txt" 문자열이 cmdTail 배열에 저장되겠죠?

아래는 간단하게 만들어본 예시입니다.

include 	c:\assembly\irvine32.inc
includelib  c:\assembly\irvine32.lib
includelib  c:\assembly\kernel32.lib
includelib  c:\assembly\user32.lib


.data
caption db "GetCommanTail Test",0
cmdTail BYTE 129 DUP(0)
       
.code
main PROC

mov edx, OFFSET cmdTail
call GetCommandTail

mov ebx, OFFSET caption
mov edx, OFFSET cmdTail
call MsgBox

    exit

main ENDP
END main

위 코드를 실행하게되면 아래와 같이 나옵니다.

 

GetMaxXY

GetMaxXY 프로시저는 콘솔 윈도우의 행과 열의 버퍼를 반환합니다. 행의 갯수는 AX로, 열의 갯수는 DX로 반환됩니다. 가능한 값의 범위는 255까지입니다. 아래는 예시입니다.

.data
rows BYTE ?
cols BYTE ?
.code
call GetMaxXY
mov rows, ax
mov cols, dx

 

GetMseconds

GetMseconds 프로시저는 EAX 레지스터에 자정 이후의 경과시간을 msec 단위로 반환합니다. 이 프로시저는 이번트 사이의 시간을 측정하는 좋은도구입니다. 아래는 예시입니다.

.data
startTime DWORD ?
.code
call GetMseconds
mov startTime, eax
L1 : 
	;loop
loop L1
call GetMseconds
sub eax,startTime

 

IsDigit

IsDigit 프로시저는 AL에 있는 값이 유효한 10진수자리에대한  ASCII 코드 인지 여부를 결정합니다. AL에 ASCII 문자를 전달합니다. 프로시저는 AL이 유효한 10진수 자릿수를 갖고있으면 Zero 플래그를 1로 설정합니다. 그렇지 않으면 0으로 설정합니다. 아래는 예시입니다.

mov AL, somechar
call IsDigit

 

MsgBox

MsgBox 프로시저는 팝업 메시지 상자를 표시합니다. 상자안에 나타낼 문자열의 오프셋은 EDX에 전달해야하고, 제목은 EBX에 전달해야합니다. 제목을 빈칸으로 두려면 EBX를 0으로 설정해야합니다. 아래는 예시입니다.

include 	c:\assembly\irvine32.inc
includelib  c:\assembly\irvine32.lib
includelib  c:\assembly\kernel32.lib
includelib  c:\assembly\user32.lib


.data
caption db "hello world",0
HelloMsg BYTE "this is Hello world box", 0dh, 0ah
		BYTE "Click OK to continue...",0
       
.code
main PROC

mov ebx, OFFSET caption
mov edx, OFFSET HelloMsg
call MsgBox

    exit

main ENDP
END main

위 코드를 실행시켜보면, 아래와 같은 화면이 나옵니다.

 

MsgBoxAsk

MsgBoxAsk 프로시저는 Yes와 No 버튼을 갖는 그래픽 팝업 메시지 상자를 표시합니다. 상자안에 나타낼 질문 문자열의 오프셋은 EDX에 전달합니다. 상자의 제목 문자열의 오프셋은 EBX에 전달합니다. 또한, MsgBoxAsk 프로시저는 EAX에 사용자가 어떤 버튼을 선택했는지 알려주는 정수를 반환합니다. 6은 Yes, 7은 No 입니다. 아래는 예시입니다.

include 	c:\assembly\irvine32.inc
includelib  c:\assembly\irvine32.lib
includelib  c:\assembly\kernel32.lib
includelib  c:\assembly\user32.lib


.data
caption db "hello world",0
AskMsg BYTE "Thank you for completing the game", 0dh, 0ah
		BYTE "Would you like to receive the results?",0
       
.code
main PROC

mov ebx, OFFSET caption
mov edx, OFFSET AskMsg
call MsgBoxAsk

    exit

main ENDP
END main

위 코드를 실행시켜보면, 아래와 같은 화면이 나옵니다.

 

 

OpenInputFile

OpenInputFile 프로시저는 입력을 위해 기존 파일을 열고, 파일의 핸들을 EAX에 넘깁니다. 열고싶은 파일의 오프셋을 EDX에 전달합니다. 파일이 성공적으로 열렸다면, EAX는 유효한 파일 핸들을 갖고 그렇지 않으면, EAX는 INVALID_HANDLE_VALUE와 같습니다. 아래는 예시입니다.

.data 
filename BYTE "myufile.txt", 0
.code
mov edx, OFFSET filename
call OpenInputFile

 

ParseDecimal32

ParseDecimal32 프로시저는 부호없는 10진수 문자열을 32비트 이진수로 변환합니다. 문자열의 오프셋은 EDX에 문자열의 길이는 ECX에 전달합니다. 아래는 예시입니다.

.data
buffer BYTE "8193"
bufferSize = ($ - buffer)
.code
mov edx, OFFSET buffer
mov ecx, bufSize
call ParseDecimal32

 

ParseInteger32

ParseInteger32 프로시저는 부호있는 10진수 문자열을 32비트 이진수로 변환합니다. 문자열의 오프셋은 EDX에 문자열의 길이는 ECX에 전달합니다. 아래는 예시입니다.

.data
buffer BYTE "-8193"
bufferSize = ($ - buffer)
.code
mov edx, OFFSET buffer
mov ecx, bufSize
call ParseDecimal32

 

Random32

Random32 프로시저는 32비트 난수 정수를 생성하고 EAX에 반환합니다. 난수는 시드라고 하는 입력을 갖는 간단한 함수를 사용하여 생성됩니다. 하나의 시드 값에 하나의 난수가 생성되는데, 난수를 여러번 생성하면 이전의 난수를 시드로 사용하다보니 난수는 의사 난수를 의미합니다. 아래는 예시입니다.

.data
randVal DWORD ?
.code
call Random32
mov randVal, eax

 

Randmize

Randmize 프로시저는 Random32 프로시저와 RandomRange 프로시저의 시작 시드 값을 초기화합니다. 시드는 100분의 1초 단위의 시간 값으로 대체됩니다. 아래는 예시입니다.

call Randomize
mov ecx, 10
L1 : call Random32
	;loop
loop L1

 

RandomRange

RandomRange 프로시저는 0부터 n-1까지 범위의 난수 정수를 생성합니다. n은 EAX에 전달해야합니다. 난수 정수는 EAX에 반환됩니다. 아래는 예시입니다.

.data
ranVal DWORD ?
.code
mov eax, 5000
call RamdomRange
mov ranVal, eax

 

ReadChar

ReadChar 프로시저는 키보드에서 한 문자를 읽고 AL 레지스터에 반환합니다. 아래는 예시입니다.

.data
char BYTE ?
.code
call ReadChar
mov char, al

ReadFromFile

ReadFromFile 프로시저는 보조기억장치에 저장된 파일을 메모리 버퍼로 읽어드립니다. 읽어들일 파일의 핸들을 EAX에, 버퍼의 오프셋을 EDX에, 읽을 최대 바이트 수를 ECX에 전달합니다. ReadFromFile 프로시저가 반환될때 Carry 플래그의 값을 확인해야합니다. CF 가 0이면 잘 읽어들였으며 EAX에 파일에서 읽은 바이트수가 저장되지만 CF가 1이면 오류가 난것이며 EAX에 오류코드를 저장합니다. 아래는 예시입니다.

.data
BUFFER_SIZE = 5000
buffer BYTE BUFER_SIZE DUP(?)
bytesRead DWORD;
.code
mov edx, OFFSET buffer
mov ecx,BUFFER_SIZE
;mov eax, fileHandle
call ReadFromFile

 

ReadDec

ReadDec 프로시저는 키보드에서 32비트 부호없는 10진수를 읽어서 EAX에 반환합니다. 만약 123ABC가 입력되었다면 반환값은 123입니다. 아래는 예시입니다.

.data
intVal DWORD ?
.code
call ReadDec
mov intVal, eax

 

ReadHex

ReadHex 프로시저는 키보드에서 32비트 16진수를 읽어서 EAX에 반환합니다. 만약 123ABC가 입력되었다면 반환값은 123ABC 입니다. 아래는 예시입니다.

.data
hexVal DWPRD ?
.code
call ReadHex
mov hexVal, eax

 

ReadInt

ReadInt 프로시저는 키보드에서 32비트 부호있는 정수를 읽어서 EAX에 반환합니다. 숫자앞의 +와 -기호는 선택사항으로 입력할 수 있습니다. -2,147,483,648부터 +2,147,483,647 내에 포함 할 수 없다면 overflow 플래그는 1로 설정되고 오류메시지를 반환합니다. 123ABC가 입력되었다면 반환값은 123입니다. 아래는 예시입니다.

.data
intVal DWORD ?
.code
call ReadHInt
mov intVal, eax

 

ReadKey

ReadKey 프로시저는 키보드가 눌렸는지 알아보기 위하여 키보드 입력 버퍼를 조사합니다. 키 데이터가 발견되지 않으면 Zero 플래그가 1로 설정되며, 만약 발견이 된다면 Zero 플래그가 0으로 설정됩니다. 또한 입력 키에따라 AL에 ASCII 코드가 설정되고 만약 0이 설정되면 특수키(방향키, 커서 화살표)를 누른것이다. AH에는 가상 스캔 코드가, DX에는 가상키 코드가 EBX에는 키보드 플래그 비트가 설정됩니다. 아래는 예시입니다.

call RadKey

 

ReadString

ReadString 프로시저는 키보드에서 문자열을 읽어들이고 Enter 키를 누를때에 멈춥니다. 읽어들인 문자열을 저장할 버퍼의 오프셋을 EDX에 전달하고 ECX에 얼만큼 저장할건지 설정합니다.(사용자가 입력할 수있는 최대 문자수에 1을 더한 값). 이후 프로시저는 사용자가 입력한 문자수를 EAX에 반환합니다. 아래는 예시입니다.

.data
buffer BYTE 31 DUP(0)	;input buffer
byteCount DWORD ?		;hild counter
,ode
mov edx, OFFSET buffer		
mov ecx, SIZEOF buffer
call ReadString
mov byteCount, eax

 

SetTextColor

SetTextColor 프로시저는 텍스트 출력에대한 전경색과 배경색을 설정합니다. 색 속성을 AX에 지정합니다. 아래는 색 속성입니다.

Black = 0 red = 4 gray = 8 lightred = 12
blue = 1 megenta = 5 lightBlue = 9 lightMagenta = 13
green = 2 brown = 6 lightGreen = 10 yellow = 13
cyan = 3 lightGray = 7 lightCyan = 11 white = 15

배경색은 높은 자릿숫자에, 전경색은 낮은 자릿숫자에 저장해야합니다. 예를 들어 파란 배경에 노란 글자는 1Dh 입니다.

아래는 예시입니다.

.code
mov AX, 1Dh		;set background : blue, textColor : yellow
call SetTextColor

 

StrLength

StrLength 프로시저는 널 종료 문자열의 길이를 반환합니다. 문자열의 오프셋을 EDX에 전달 하면, 프로시저는 문자열의 길이는 EAX에 반환합니다. 아래는 예시입니다.

.data
buffer BYTE "abcde", 0
bufLength DWORD ?
.code 
mov edx, OFFSET buffer
call StrLength
mov bufLength, eax

 

waitMsg

waitMsg 프로시저는 "Press any key to continue..." 라는 메시지를 표시하고 사용자가 키를 누르기를 기다립니다. 다음은 예시입니다.

call WaitMsg

 

WriteBin

WriteBin 프로시저는 정수를 ASCII 이진수 형식으로 콘솔 윈도우에 출력한다. 정수를 EAX에 전달합니다. 이진수 비트는 4개씩 묶어서 표시됩니다. 아래는 예시입니다.

mov eax, 12345AF9h
call WriteBin

아래는 위 코드를 실행했을때 결과입니다.

 

WriteBinB

WriteBinB 프로시저는 32비트 정수를 ASCII 이진수 이진수 형식으로 콘솔 윈도우에 표시합니다. 값을 AX에 전달하고 EBX는 표시할 크기를 바이트 단위(1, 2, 4)로 지시합니다. 아래는 예시입니다.

mov ax, 5678h
mov ebx, TYPE WORD
call WriteBinB

 아래는 위 코드를 실행했을때, 화면입니다.

 

WriteChar

WriteChar  프로시저는 콘솔 윈도우에 하나의 문자를 출력합니다. 문자를 AL에 전달합니다. 아래는 예시입니다.

mov al, 'A'
call WriteChar

 

WriteDec

WriteDec 프로시저는 32비트 부호없는 정수를 10진수 형식으로 콘솔 윈도우에 출력합니다. 정수를 EAX에 전달합니다. 다음은 예시입니다.

mov eax, 311
call WriteDec

 

WriteHex

WriteHex 프로시저는 32비트 부호없는 정수를 8자리 16진수 형식으로 출력합니다. 필요하면 0이 삽입됩니다. 정수를 EAX에 전달합니다. 다음은 예시입니다.

mov eax, 8F8Fh
call WriteHex

아래는 실행 화면입니다.

 

WriteHexB

WriteHexB 프로시저는 32비트 부호없는 정수를 16비트 형식으로 콘솔 윈도우에 표시합니다. 정수를 EAX에 전달하고 EBX는 표시할 크기를 바이트 단위(1,2,4)로 표시합니다. 다음은 예시입니다.

mov eax, 88FFh
mov ebx, TYPE DWORD
call WriteHexB

 

WriteInt

WriteInt 프로시저는 32비트 부호있는 정수를 부호는 포함하고 앞에 0이 없는 10진수 형식으로 콘솔 윈도우에 출력합니다. 정수를 EAX에 전달합니다. 아래는 예시입니다.

mov eax, -213141
call WriteInt

아래는 실행 화면입니다.

 

WriteString

WriteString 프로시저는 널 종료 문자열을 콘솔 윈도우에 출력합니다. 문자열의 오프셋을 EDX에 전달합니다. 아래는 예시입니다.

.data
string BYTE "Hello world", 0
.code
mov edx, OFFSET string
call WriteString

 

WriteToFile

WriteToFile 프로시저는 버퍼의 내용을 출력 파일에 저장합니다. 저장할 파일의 핸들을 EAX에, 버퍼의 오프셋을 EDX에, 출력할 바이트 수를 ECX에 전달합니다. 프로시저가 반환될때, EAX가 0보다 크면 EAX는 출력된 바이트수가 반환된 것이며, 0보다 작으면 오류가 발생한 것입니다. 다음은 예시입니다.

BUFFER SIZE = 1000
.data
fileHandle DWORD ?
buffer BYTE BUFFER_SIZE DUP(?)

.code eax, fileHandle
mov edx, OFFSET buffer
mov edx, BUFFER_SIZE
call WriteToFile

 

WriteWindowMsg

WriteWindowMsg 프로시저는 시스템 함수에대한 호출을 수행할 때 응용 프로그램에서 발생한 가장 최근의 오류를 나타내는 문자열을 표시합니다. 이것은 프로그램이 파일을 생성하거나 열수 없을 때 사용하면 좋습니다. 아래는 예시입니다.

call WriteWindowMsg

 

이것으로 라이브러리 프로시저 설명을 마치도록 하겠습니다. 

Comments