HyeM

[컴퓨터구조]4주차_서브루틴과 명령어 구분 본문

Study/Computer Architecture

[컴퓨터구조]4주차_서브루틴과 명령어 구분

Hailey_HyeM207 2020. 5. 30. 00:11

 분기 명령어

분기 : 다른곳으로 이동하는 것

형태 :

  • BRZ(branch if zero) 211 : 조건분기; 조건코드가 0이면 211로 분기하라는 명령어

  • BR 202 : 무조건분기; 무조건 202번지로 분기하라는 명령어

  • BRE(branch if equal) R1, R2,235 : 조건분기; 레지스터R1과 레지스터 R2이 내용이 같다면 235번지로 분기하라는 명령

 

 

 

 

 

 

명령어가 저장되어 있는 부분은 메모리의 코드 영역이다.

202 :  SUB X, Y

203 : BRZ 211 ; 202번지의 x-y가 0이면(x와 y가 같다면), 203번지의 BRZ 211에서 분기를 할 것이다.

210 : BR 202 ; 무조건 202번지로 분기해야 된다.

225 : BRE R1, R2, 235 ; 레지스터 R1과 레지스터 R2의 내용이 같다면 235번지로 분기한다.

 

 

 

 

 

서브루틴과 스택

스택

- LIFO(후입선출)방식

- PUSH & POP 연산자 

     PUSH(a, b): 스택에 데이터를 저장

     POP() : 스택의 데이터 인출

- SP & BP 포인터 :

     SP : 스택포인터 (스택의 맨 꼭대기를 가리킴)

     BP : 베이스포인터 (스택의 한 지점을 가르킴) 

 

 

 

서브루틴

MAIN과 서브루틴 SUB1, 서브루틴 SUB2로 구성된 프로그램

1. Main 부터 시작하여, PC레지스터 등과 함께 각 번지의 명령어가 실행이 된다.

   ( main )200,201,202...

2. Main의 210 번지의 CALL SUB1 명령어를 만나면, 210번지에서 250번지로 분기하게된다. (이때, PC값이 바뀜)

   ( main )210  → ( SUB1 )250,251...

3. SUB1의 250번지 부터 명령어를 처리하다가, 260의 CALL SUB2를 만나면, 300번지로 이동하여 SUB2의 300번지부터RET(return)까지 명령어 실행후,  SUB1의 260번지의 다음인 261번지로 돌아온다. 

   ( SUB1 )260  → ( SUB2 )300,301,RET → ( SUB1 )261

4. SUB1의 261번지에서 명령을 실행하다가 CALL SUB2를 또 호출하게 되면, SUB2의 300번지로 이동하여, RET까지 실행하고 다시, SUB1의 281번지로 돌아온다.

   ( SUB1 ) 280 → ( SUB2 )300,301,RET → ( SUB1 )281

5. SUB1의 RET까지 실행하면, SUB1을 벗어나 다시 main의 211번지로 돌아오게되고, END까지 실행하면 프로그램이 종료된다.

 ( SUB1 )RET -> ( main )211,212....END

6. 프로그램이 종료되면, 스택,힙,데이터 등 메모리에 담겨 있던 프로그램 정보가 초기화 된다. 

 

 

 

서브루틴과 스택

위의 서브루틴 수행과정은 스택의 변화로 가능하다. 

(A) 초기상태

초기엔, 스택이 비어있는 상태로, sp(스택포인터)는 스택의 맨 꼭대기를 가르킨다. 

(B) SUB1 호출 후

main의 210번지 CALL SUB1 : SUB1을 호출하면, sub1로 넘어가기 전에, main으로 돌아올 수 있도록 호출한 다음 주소(211)번지를 스택에 저장한다. (PUSH)

(C) SUB2 호출 후

SUB1의 260번지 CALL SUB2 : SUB1에서 SUB2를 호출하게 되면, SUB2로 넘어가기전에, 스택에 SUB1로 돌아올 번지(261)를 저장한다. (PUSH)

(D) SUB2 복귀후

SUB2의 RET : SUB2에서 RET을 만나면, 스택에서 돌아갈 주소 261(SUB1)를 POP하여, 261번지로 이동(복귀)한다. (POP)

(E) SUB2 호출 후

SUB1의 280번지 CALL SUB2 : SUB1에서 다시 SUB2를 호출하게 되면, SUB2로 넘어가기 전에, 스택에 돌아올 주소 281번지를 저장한다. (PUSH)

(F) SUB2 복귀 후

SUB2의 RET  :  SUB2에서 RET을 만나면, 스택에서 돌아갈 주소 281을 POP 하여, 281번지로 이동(복귀한다) (POP)

(g) sub1 복귀 후

SUB1의 RET : SUB1에서 RET을 만나면, 스택에서 돌아갈 주소 211번지를 POP하여, 211번지의 main으로 돌아간다. ( POP)

 

 

 

 

 

 

 

명령어 분류

# 오퍼랜드에 저장되는 데이터 형태

 - 주소 : 주기억장치의 주소나 레지스터의 주소 

 - 수 : 정수, 고정-소수점 수, 부동-소수점 수 

 - 문자 : ASCII 코드 

 - 논리 데이터 : 비트(bit) 혹은 플래그(flag) 

 

#  오퍼랜드가 주소를 나타내는 경우 

오퍼랜드 수에 따라, 3, 2, 1, 0 주소 방식이 있다.

 

 

# 1주소 명령어

- 오퍼랜드 한 개만 포함하는 명령어

- 오퍼랜드 데이터 형태는 주소

LOAD X     ; AC <- M[x] (x번지의 데이터를 누산기에 저장)

LOAD : 주메모리  RAM의 x주소를 가져옴.

어셈블리어에서 ;는 주석 

M 메모리 , [ ]는 포인터

 

# 2주소 명령어

- 오퍼랜드 2개를 포함하는 명령어

- 오퍼랜드 2개 모두 주소 저장

MOV  X, Y ; M[X] ← M[Y]   _ 메모리 y의 data를 메모리 x로 이동시킴.

x가 destination, y가 source를 의미함. 

 

 

 

# 3주소 명령어

- 오퍼랜드 3개를 포함하는 명령어

- 레지스터의 주소를 저장하는 명령어 형식

-  보통은 오퍼랜드1과 오퍼랜드2를 연산해서 오퍼랜드3에 저장하는 것이 일반적이지만, 

ADD R1, A, B 같은 경우 오퍼랜드2와 오퍼랜드 3을 연산하여 오퍼랜드1에 저장하는 경우가 많이 사용된다.

ADD X, Y, Z   ; M[Y] +M[Z]  _ z번지 데이터와 y의 데이터를 더하여, x에 저장한다.

X는 destiantion, Y는 source 2, Z는 source1을 의미한다.

 

 

 

 

 

 

 

 

명령어를 사용한 연산 프로그램

0주소 명령어 ~ 3주소 명령어까지, 총 4가지 주소 형식으로   X=B*(C+D*E-F/G) 의 수식연산 프로그램을 구현&비교해보자.

명령어

 

 

 

0주소 명령어 사용한 X=B*(C+D*E-F/G) 프로그램

- 0주소 명령어는와 스택의 PUSH와 POP 연산이용

- 0주소는 stor 명령어를 사용할 수 없음 

100  PUSH B     ; 스택에 B가 입력됨
101  PUSH C     ; 스택에 C가 입력됨
102  PUSH D     ; 스택에 D가 입력됨
103  PUSH E     ; 스택에 E가 입력됨
104  MUL           ; E와 D를 연속해서 POP 하고 곱셈을 수행한 후 결과를 PUSH
105  ADD           ; E*D의 결과를 C를 연속해서 POP 하고 더한 후 결과를 PUSH
106  PUSH F     ; 스택에 F가 입력됨
107  PUSH G    ; 스택에 G가 입력됨
108  DIV             ; G와 F를 연속해서 POP하고 나눗셈을 수행한 후 결과를 PUSH
109  SUB           ; F/G와 C+E*D를 연속해서 POP하고 뺄셈을 수행 후 결과를 PUSH
110  MUL           ; (C+D*E-F/G)와 B를 연속해서 POP하고 곱셈을 수행 후 결과 PUSH 
111  POP           ; 기억장치 X번지에 저장하기 위해 결과를 POP 


(A)(B) 100~104 : 스택에 B, C, D, E를 차례대로 입력후, - 기호를 만나면, E와 D를 pop해 곱셈한 후 결과를 PUSH
(C) 105 : E*D의 결과와 C를 연속해서 더하여 push 한다.  ( ( )로 묶여있기 때문에, B와의 계산은 괄호를 만나기 전까지 연산 하지 않는다. )
(D)(E) 106~108 : 그 다음 F와 G를 PUSH하고, POP하여, 나눗셈을 수행하고 그 결과를 PUSH 한다.
(F)109 : 그리고, 방금 계산한 F/G와 C+D*E 의 뺄셈 연산을 위해 POP하여, 뺄셈을 수행하고 그 결과를 PUSH한다.
(G) 110 : 마지막으로 남은 B와 (C+D*E-F/G)의 곱셈연산을 위해, POP하여 곱셈 수행후, 결과를 PUSH 한다.
(H) 111 : 최종 결과를 기억장치 X번지에 저장하기 위해 결과를 POP 한다. 

 

 

1주소 명령어를 사용한 X=B*(C+D*E-F/G) 프로그램

- 0주소보다 더 복잡하고, 시스템에서 보다 많은 양 처리& 많은 시간 걸림

- 코드가 짧아짐

-  M[A] : 기억장치 A번지에 저장된 데이터내용

-  T : 기억장치 내의 임시 저장장소의 주소

100   LOAD F        ; AC  ← M[F]
101   DIV G            ; AD ← AC / M[G] 
102   STOS T        ; M[T] ← AC 
103   LOAD D       ; AC ← M[D] 
104   MUL E          ; AC ← AC * M[E] 
105   ADD C          ; AC ← AC + M[C] 
106   SUB T          ; AC ← AC - M[T] 
107   MUL B          ; AC ← AC  / M[B]
108   STOS X        ; X[X] ← AC

100 : F의 데이터를 AC(누산기)로 가져온다.
101 : 누산기의 값을 g로 나눈다 ( F/G ). 
102 위의 결과를 기억장치 내의 임시 저장장소 주소인 T에 넣어논다.
103 : D의 데이터를 누산기로 가져온다.
104 : 누산기의 값과 E와 곱셈연산을 하고 다시 누산기에 넣고, (D*E)
105 : 누산기의 값과 C와 덧셈연산을 하고 다시 누산기에 넣는다. (C+D*E)
106 : 연산이 끝나면 누산기와 임시 저장해놓은 T의 뺄셈연산을 한다. ( (C+D*E)-F/G )
107 : 마지막으로  누산기를 이용해 B와 곱셈 연산을 해준다. ( B*(C+D*E-F/G) )
108 : 최종 연산 결과를 X에 저장한다. 

 

 

 

2주소 명령어를 사용한  X=B*(C+D*E-F/G) 프로그램

- M[A] : 기억장치 A번지에 저장된 데이터 내용

- R1, R2 : CPU내에 위치한 레지스터

- MOV (DESTINATION) (SOURCE)  

- SUB  (1) (2)  // (1)-(2)

100   MOV R1, D    ; M[R1] ← M[D]
101  MUL R1, E     ; M[R1] ← M[R1] * M[E]
102   MOV R2,F     ; M[R2] ← M[F]
103   DIV R2, G     ; M[R2] ← M[R2] / M[G]
104   SUB R1, R2   ; M[R1] ← M[R1] - M[R2]
105   ADD R1, C    ; M[R1] ← M[R1] + M[C]
106   MUL R1, B    ;  M[R1] ← M[R1] * M[B]
107   MOV X, R1  ; M[X] ← M[R1]

100 : D의 데이터를 레지스터 R1에 저장한다.
101 : 레지스터 R1로 E를 가져와 곱한다. (D*E)
102 : 레지스터 R2로 F를 가져온다.
103 : 레지스터 R2로 G를 가져와 나눈다. (F/G)
104 : 레지스터 R1에서 레지스터 R2를 빼서 R1에 저장한다. ((D*E)-(F/G))
105 : 레지스터R1에 C를 더한다. (C+(D*E-F/G))
106 : 레지스터 R1에 B를 곱한다. (B*(C+(D*E-F/G)))
107 : 모든 연산 후에는,  레지스터 R1의 값을  기억장치의 X에 저장한다.

 

 

 

3주소 명령어를 사용한 X=B*(C+D*E-F/G) 프로그램

- 3개의 오퍼랜드 모두 주소를 나타냄

- M[A] : 기억장치 A번지에 저장된 데이터 내용

- R1, R2 : CPU내에 위치한 레지스터

- MUL (SOURCE1) (SOURCE2) (DESTIANTION) // S1 *S2 하여 DESTINATION에 저장한다. 

100   MUL D, E, R1        ;M[R1] ← M[D] * M[E]
101   ADD C, R1, R1      ;M[R1] ← M[C] * M[R1]
102   DIV F, G, R2           ;M[R2] ← M[F] * M[G]
103   SUB R1, R2, R1    ;M[R1] ← M[R1] * M[R2]
104   MUL B, R1, X         ;M[X] ← M[B] * M[R1]

100 : D와 E를 곱하여 레지스터 R1에 저장한다. 

101 : R1과 C를 더하여 R1에 저장한다.

102 : F에서 G를 나누어 R2에 저장한다.

103 : R1에서 R2를 빼어 R1에 저장한다.

104 : B에서 R1을 곱하여 X에 저장한다. 

 

 

 

명령어 주소 개수에 따른 장단점

> 주소 개수가 많은 경우

장점 : 레지스터 수가 많아져서, 연산 속도가 빨라짐

         프로그램이 짧아져서, 프로그램 당 명령어 수가 감소함

단점 : 저장한 오퍼랜드의 수가 많아지기 때문에 명령어가 더 복잡해짐

 

> 주소 개수가 적은 경우

장점 : 오퍼랜드의 수가 적어서 간단하므로, 명령어 인출과 실행 속도가 높아짐

단점 : 프로그램의 길이가 증가함

 

 


출처 :

2019 컴퓨터 구조 호준원 교수님 강의노트

디지털논리와 컴퓨터 설계, Harris et al. (조영완 외 번역), 사이텍미디어, 2007, 

컴퓨터 구조와 원리 (비주얼 컴퓨터 아키텍처), 신종홍 저, 한빛미디어, 2011

 


문제출제

1. 다음 보기를 읽고, O,X 로 표기하시오

(1) BR 201 ; 무조건 201번지로 분기하라는 뜻이다.  ( O , X )

(2) 202 SUB X, Y   이고 203 BRZ 211일때, X의 값이 10이고, Y의 값이 9이면, 203번지의 명령어 수행시, 211번지로 분기한다. O , X )

 

2. 다음 중 옳은 것을 고르시오.

1) 스택에는 함수의 return address와 매개변수등이 저장된다.

2) sp포인터는 스택의 꼭대기를 가르킨다.

3) 201번지의 call sub 1의 명령어를 실행하면(sub1의 코드 시작주소는 240번지), sub1의 240번지로 분기하여 명령어를 실행한다.

4) 서브루틴 sub2에서 RET를 만나면, sub2를 호출했던 코드(call sub2)로 이동한다. 

5) 프로그램 종료시, 스택이 초기화 된다. 

 

3. 다음 스택의 빈칸에 들어갈 데이터를 쓰시오. 

 

ㄱ : ______   ㄴ : _______

 

4. 다음 명령어에 해당하는 설명을 고르시오.

(1) SUB R1, R2, R1

( M[R1] ←M[R2] -M[R1]  , M[R1]←M[R1]-M[R2])

(2) MUL D, E, R2

( M[R2] ← M[D] + M[E], M[R2] ←M[D] *M[E], M[D] ←M[E]*M[R2])

(3) MOV R1, R2

( M[R1] ← M[R2] ,  M[R2] ← M[R1] )

 

 

5. 다음 보기를 읽고 O,X로 표기하시오.

(1) 같은 프로그램에서, 3주소 명령어는 1주소 명령어보다  명령어 수가 적게 필요하지만, 명령어가 복잡해지고, 속도가 다소 느리다. ( O , X )

(2)  X= B*( C+D*E-F/G) 연산에서 명령어 실행시, X로 저장하는 연산을 제외하고, 가장 마지막으로 연산되는 것은 B와  ( C+D*E-F/G) 의 연산이다.( O , X )

 

답은 밑의 더보기 클릭

 

 

더보기

문제출제

1. 다음 보기를 읽고, O,X 로 표기하시오

(1) BR 201 ; 무조건 201번지로 분기하라는 뜻이다.  ( O , X )

BR은 무조건 분기여서, 맞다.

(2) 202 SUB X, Y  이고 203 BRZ 211일때, X의 값이 10이고, Y의 값이 9이면, 203번지의 명령어 수행시, 211번지로 분기한다. O , X )

BRZ는 조건 코드가 0이면 분기하기 때문에 아니다. ( 0이 아닌 1이기 때문에 조건 만족 X )

 

2. 다음 중 옳은 것을 고르시오.

1) 스택에는 함수의 return address와 매개변수등이 저장된다.
스택에는 함수 호출과 관계되는 지역변수와 매개변수, return address 가 저장이 된다.

2) sp포인터는 스택의 꼭대기를 가르킨다.
맞다. sp 포인터는 스택의 꼭대기를 가르켜서, pop과 push되는 위치를 관리한다.

3) 201번지의 call sub 1의 명령어를 실행하면(sub1의 코드 시작주소는 240번지), sub1의 240번지로 분기하여 명령어를 실행한다.
call sub1 로 sub1함수를 호출했으므로, sub1의 시작코드 240번지로 가는것이 맞다.

4) 서브루틴 sub2에서 RET를 만나면, sub2를 호출했던 코드(call sub2)로 이동한다. 
SUB2를 호출했던 코드가 아닌 그 다음 코드로 이동한다. (EX. 105 CALL SUB2라면, 돌아올땐 106번지로 돌아온다. 

5) 프로그램 종료시, 스택이 초기화 된다. 
프로그램 종료시, 스택뿐만아니라 힙, 데이터 영역, 코드 , 스택  모두 초기화 된다.

답 : 4번 

 

3. 다음 스택의 빈칸에 들어갈 데이터를 쓰시오. 

 

ㄱ : __261__ ㄴ : __281__

함수 호출하는 명령어를 만나면, 현재 명령어에 +1 한 주소값을 스택에 PUSH하여, 저장한다. 

(이유 : 돌아와서는 그 다음 명령어를 실행해야 하기 때문이다. )

 

4. 다음 명령어에 해당하는 설명을 고르시오.

(1) SUB R1, R2, R1

( M[R1] ←M[R2] -M[R1]  , M[R1]←M[R1]-M[R2])

Sub는 뺄셈, 3주소 명령어는 일반적으로 앞에서부터 뒤로  연산을 한다.

(2) MUL D, E, R2

( M[R2] ← M[D] + M[E], M[R2] ←M[D] *M[E], M[D] ←M[E]*M[R2])

MUL은 곱셈, 3주소 명령어는 일반적으로 앞에서부터 뒤로  연산을 한다. 

(3) MOV R1, R2

( M[R1] ← M[R2] ,  M[R2] ← M[R1] )

2주소 명령어(명령어 A B)에서 mul이나 div, sub 명령어는 'A 연산 B' 로 진행되는데,

mov명령어에서는  B를  A로 저장한다.

 

5. 다음 보기를 읽고 O,X로 표기하시오.

(1) 같은 프로그램에서, 3주소 명령어는 1주소 명령어보다  명령어 수가 적게 필요하지만, 명령어가 복잡해진다. ( O , X )

3주소 명령어는 오퍼랜드3개이고, 1주소 명령어는 오퍼랜드가 1개이기때문에, 3주소 명령어는 총 명령어 수가 적어진다.

(2)  X= B*( C+D*E-F/G) 연산에서 명령어 실행시, X로 저장하는 연산을 제외하고, 가장 마지막으로 연산되는 것은 B와  ( C+D*E-F/G) 의 연산이다. ( O , X )

 ( )괄호는 닫는 괄호가 나오기 전까지는 연산을 하지 않기 때문에, 위의 예시 연산에서는 b*(~)의 연산이 나중에 진행된다.

 

Comments