외로운 Nova의 작업실

Assembly 언어 공부 - 22(프로시저의 사용) 본문

Programming/Assembly

Assembly 언어 공부 - 22(프로시저의 사용)

Nova_ 2022. 8. 24. 10:36

안녕하세요, 이번 시간에는 프로시저를 사용하여 프로그램을 설계해보겠습니다. 

 

- 프로시저의 문서화

프로시저를 만들때 문서화를 하는 것은 개발해야할 좋은 습관입니다. 다음은 프로시저의 시작 부분에 넣을 수 있는 정보입니다.

 

1. 프로시저가 수행하는 모든 작업에대한 설명

2. Receive : 입력 매개변수에 대한 설명

3. Return : 프로시저가 반환하는 값에대한 설명

4. Requires : 요구 사항에대한 목록

 

위를 참고하여 세개의 32비트 정수의 합을 계산하는 SumOf라는 이름의 프로시저를 설명해보겠습니다. 3개의 정수는 호출되기전에 eax, ebx, ecx에 저장되어 있어야합니다.

;------------------------------------------------------------------------
;SumOf PROC
;
; Calculates and returns the sum of three 32-bit integers
; Receives : eax, ebx, ecx, the three integers. May be signed or unsigned
; Returns : eax = sum
;------------------------------------------------------------------------

 

- CALL 명령어와 RET 명령어

CALL 명령어는 피연산자인 프로시저 주소로 가서 프로시저를 실행시키는 명령어 입니다. 이후 프로시저를 실행시키다가 RET 명령어를 만나면 다시 CALL 명령어가 호출된 주소로 돌아옵니다. 이 과정을 진행할때 스택이 사용됩니다. 이에대해 순서대로 알아봅시다.

 

1. CALL 명령어 사용

2. CALL 다음 주소를 스택에 푸쉬

3. 실행할 프로시저의 주소를 EIP에 입력

4. EIP에 저장된 주소(실행할 프로시저의 주소)로 가서 명령어 실행

5. RET 명령어 사용

6. 스택에 저장된 CALL 다음 주소를 EIP에 팝

7. EIP에 저장된 주소(CALL 다음 주소)로 가서 명령어 실행

 

- 순서도

순서도는 프로그램의 논리를 그리는 잘 확립된 방법입니다. 순서도에서 각 도형은 하나의 논리 단계를 나타내고 도형을 연결하는 화살표 선은 논리 단계의 순서를 보야줍니다. 네모는 일반적인 처리, 세모는 조건부, 동그라미는 시작과 끝을 의미합니다. 그렇다면 정수 배열을 받아 배열 안에 들어있는 정수를 모두 더하여 eax로 return 하는 프로시저를 순서도로 그려보도록 하겠습니다.

 

- USES 연산자

USES 연산자는 어셈블러에게 2가지 일을 하도록 하게합니다. 첫째, 프로시저의 시작에 스택에 레지스터를 저장하는 PUSH 명령어를 생성합니다. 둘째, 프로시저의 끝에 레지스터의 값을 복원하는 POP 명령어를 생성합니다. 아래는 예시입니다.

ArraySum PROC USES esi, ecx
	
    mov eax, 0
    
L1: 
    add eax, [esi]
    add esi, TYPE WORD
    loop L1
    
    ret

ArraySum ENDP

;위 코드는 어셈블러가 아래 코드로 변환시킵니다.

ArraySum PROC 
	
    push esi
    push ecx
    mov eax, 0
    
L1: 
    add eax, [esi]
    add esi, TYPE WORD
    loop L1
    
    pop ecx
    pop esi
    
    ret

ArraySum ENDP

 

- 스터브 프로그램(stub programm)

스터브 프로그램 이라고하는 최소 버전의 프로그램을 만들어봅시다. 이 프로그램은 빈 프로시저만 포함합니다. 프로그램은 어셈블되고 실행되지만 어떠한 유용한 일도 하지않을 것입니다.

;this program prompts the user for three integers
;store them it an array, calculates the su of the array, and display the sum

.code
main PROC

;Main program control procedure
;Calls : clrscr, PromptForIntegers, ArraySum, DisplaySum

exit

main ENDP

;--------------------------------------------------------------------------
PrompltForIntegers PROC
;
;prompt the user for three 32-bit integers
;store them in array
;Receive : ESI points to an array of doubleword integers, ecx = array size
;Retruns : nothing
;calls : ReadInt, WriteString
;--------------------------------------------------------------------------
	ret
    
PromptForIntegers ENDP

;-------------------------------------------------------------------------
ArraySum PROC
;
;Calculate the sum of an array of 32-bit Integers
;Receive : ESI points to an array, ecx - array size
;Returns : eax = sum of the array elements
;-----------------------------------------------------------------------

	ret
    
ArraySum ENDP

;-----------------------------------------------------------------------
DisplaySum PROC
;
;Display the sum on the screen
;Receive : eax = the sum
;Returns : nothing
;Calls : WriteString,  WriteInt
;------------------------------------------------------------------------

	ret
    
DisplaySum ENDP

END MAIN

 

- 구조 차트

구조 차트란 프로그램의 PROC 구조를 기술합니다. 링크 라이브로리의 프로시저는 음영처리를합니다. 위 코드를 기반으로 구조 차트를 만들어보겠습니다.

지금은 작은 프로그램이지만, 정말 큰 프로그램을 만들때는 꼭 필요한 차트입니다. 이제 실제로 ArraySum 프로그램을 구현해보도록 하겠습니다.

 

- 프로시저를 이용한 ArraySum 프로그램 구현

;this program prompts the user for three integers
;store them it an array, calculates the su of the array, and display the sum


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


.data
INTEGER_COUNT = 3
str1 BYTE "Enter a signed integer : ", 0
str2 BYTE "The sum of the integers is: ", 0
intArray DWORD INTEGER_COUNT DUP(?)

   

.code
main PROC

    call Clrscr
    mov esi, OFFSET intArray
    mov ecx, INTEGER_COUNT
    call PromptForIntegers
    call ArraySum
    call DisplaySum

exit
main ENDP

;--------------------------------------------------------------------------
PromptForIntegers PROC USES ecx edx esi
;
;prompt the user for three 32-bit integers
;store them in array
;Receive : ESI points to an array of doubleword integers, ecx = array size
;Retruns : nothing
;calls : ReadInt, WriteString
;--------------------------------------------------------------------------
    mov edx, OFFSET str1
L1: call WriteString
    call ReadInt
    call Crlf
    mov [esi], eax
    add esi, TYPE DWORD
    loop L1
    ret
PromptForIntegers ENDP

;-------------------------------------------------------------------------
ArraySum PROC USES esi ecx
;
;Calculate the sum of an array of 32-bit Integers
;Receive : ESI points to an array, ecx - array size
;Returns : eax = sum of the array elements
;-----------------------------------------------------------------------
    mov eax, 0
L1: add eax, [esi]
    add esi, TYPE DWORD
    loop L1
    ret
ArraySum ENDP

;-----------------------------------------------------------------------
DisplaySum PROC USES edx
;
;Display the sum on the screen
;Receive : eax = the sum
;Returns : nothing
;Calls : WriteString,  WriteInt
;------------------------------------------------------------------------
    mov edx, OFFSET str2
    call WriteString
    call WriteInt
    call Crlf
    ret
DisplaySum ENDP

END MAIN

위 코드를 실행하면 아래와 같은 결과가 나옵니다.

Comments