1. 분기 명령어
- BRZ(Branch if Zero) 주소번지 : 조건코드가 0이면 지정 주소 번지로 분기하라는 명령어
- BR 주소번지 : 무조건 지정 주소 번지로 분기하라는 명령어
- BRE(Branch if Equal) R1 R2 주소번지 : 레지스터 R1, R2의 내용이 같다면 지정 주소번지로 분기하라는 명령어
* 분기하다 : 프로그램의 실행 순서를 변경하여 다른 명령을 실행할 수 있게 하다
위의 개념을 알고 아래와 같은 예시를 해석하면 다음과 같이 해석할 수 있다
2. 서브루틴
- 사용자가 원해서 메인에서 진행을 하다 다른 코드 블록에 가 처리하고 결과를 얻는 것
- CALL로 블록을 호출을 하고 RET 호출한 곳으로 복귀한다
1) 호출 명령어 CALL
- 현재 PC(Program Counter)에 있는 현재 주소 번지의 다음 번지(복귀했을 때 실행할 번지)를 스택에 저장하고 호출한 서브루틴의 시작 주소를 PC에 넣어 호출한 서브루틴으로 분기한다
▶ 주 프로그램(main)에서 SUB1을 호출하면 현재 주소 번지의 다음 번지가 스택에 저장이 된다. 이는 서브루틴에서 복귀 했을 때 실행할 주소를 저장했다 볼 수 있다 (PUSH)
2) 복귀 명령어 RET
- RET을 만나면 블록을 마무리하고 스택에 저장되어 있던 주소 번지를 PC에 넣어 분기한다. (CALL 명령어 다음 주소로)
▶ RET을 만나면 다시 주 프로그램(main)으로 돌아가 호출한 다음 번지인 211로 분기한다
▶ 그리고 스택에 있던 값이 사라진다 (POP)
3. 명령어 분류
1) 오퍼랜드에 저장되는 데이터나 형태
- 주소 : 주기억장치의 주소나 레지스터의 주소
- 수 : 정수, 고정-소수점 수, 부동-소수점 수
- 문자 : ASCII 코드
- 논리 데이터 : 비트 혹은 플래그
2) 오퍼랜드가 주소를 나타내는 경우
- 오퍼랜드 수에 따라 0, 1, 2, 3 주소 방식이 존재한다
(1) 0주소 명령어
- OP code부만 있고 주소를 지정하는 자료부가 없는 명령어
- 모든 연산은 stack 메모리의 가장 위를 가리키는 operand를 이용해 명령어를 수행한다
- 스택에 있는 데이터만을 이용해 연산을 수행하므로 인스트럭션 수행시간이 짧다
* 인스트럭션 : 컴퓨터에게 일을 시키는 단위로, 컴퓨터가 알아들을 수 있는 기계어로 이루어져 있는 명령
- 다른 주소 명령어들과 다르게 STOR를 사용하지 않음 (PUSH, POP 사용)
< 0주소 명령어를 이용해 X = B * (C + D * E – F / G) 표현하기 >
명령어 | 동작 |
PUSH B | 스택에 B 저장 |
PUSH C | 스택에 C 저장 |
PUSH D | 스택에 D 저장 |
PUSH E | 스택에 E 저장 |
MUL | 스택 가장 위에 있는 E와 D를 MUL(곱하기) 연산 수행 후 결과를 PUSH |
ADD | 스택 가장 위에 있는 (E*D)와 C를 ADD(더하기) 연산 수행 후 결과 PUSH |
PUSH F | 스택에 F 저장 |
PUSH G | 스택에 G 저장 |
DIV | 스택 가장 위에 있는 F와 G를 DIV(나누기) 연산 수행 후 결과를 PUSH |
SUB | 스택 가장 위에 있는 (F/G)와 (E*D+C)를 SUM(빼기) 연산 수행 후 결과를 PUSH |
MUL | 스택 가장 위에 있는 (E*D+C) – (F/G)와 B를 MUL(곱하기) 연산 수행 후 결과를 PUSH |
POP | 스택에 저장되어 있는 결과를 꺼내 출력된다 |
아래와 같은 상황임
(2) 1주소 명령어
- 오퍼랜드 한 개만 포함하는 명령어로 오퍼랜드 형태는 주소이다
- 결과는 자동으로 누산기(AC)에 저장되고 AC를 이용해 명령어를 처리한다
- 어셈블리 언어로 표현한 예
LOAD X : X번지 데이터를 가져와 누산기에 저장한다는 의미
< 1주소 명령어를 이용해 X = B * (C + D * E – F / G) 표현하기 >
명령어 | 동작 |
LOAD F | F의 값을 누산기에 저장 |
DIV G | 누산기에 있는 값(F)과 G를 DIV(나누기) 연산 수행 후 결과를 누산기에 저장 |
STOS T | 누산기에 있는 값(F/G)을 T에 저장 |
LOAD D | D의 값을 누산기에 저장 |
MUL E | 누산기에 있는 값(D)과 E를 MUL(곱하기) 연산 수행 후 결과를 누산기에 저장 |
ADD C | 누산기에 있는 값(D*E)과 C를 ADD(더하기) 연산 수행 후 결과를 누산기에 저장 |
SUB T | 누산기에 있는 값(D*E+C)과 T(F/G)에 있는 값을 SUB(빼기) 연산 수행 후 결과를 누산기에 저장 |
MUL B | 누산기에 있는 값(D*E+C - F/G)과 B를 MUL(곱하기) 연산 수행 후 결과를 누산기에 저장 |
STOS X | 누산기에 있는 값(B*(D*E+C – F/G))를 X에 저장 |
(3) 2주소 명령어
- 오퍼랜드 2개를 포함하는 명령어 형식으로, 오퍼랜드 2개 모두 주소를 저장하는데 사용한다
- 실행속도가 빠르며 기억 장소를 많이 차지하지 않음
- 연산 결과는 주로 오퍼랜드1(레지스터1)에 저장되기 때문에 오퍼랜드1의 원래 데이터는 사라진다
- 어셈블리 언어로 표현한 예
MOV X, Y : Y번지의 데이터를 X번지에 넣기
< 2주소 명령어를 이용해 X = B * (C + D * E – F / G) 표현하기 >
명령어 | 동작 |
MOV R1, D | D의 값을 R1으로 이동 |
MUL R1, E | R1(D)의 값과 E의 값을 MUL(곱하기) 연산 후 R1에 저장 |
MOV R2, F | F의 값을 R2로 이동 |
DIV R2, G | R2(F)의 값과 G의 값을 DIV(나누기) 연산 후 R2에 저장 |
SUB R1, R2 | R1의 값(D*E)과 R2의 값(F/G)을 SUB(빼기) 연산 후 R1에 저장 |
ADD R1, C | R1의 값(D*E – F/G)과 C를 ADD(더하기) 연산 후 R1에 저장 |
MUL R1, B | R1의 값(D*E – F/G + C)과 B를 MUL(곱하기) 연산 후 R1에 저장 |
MOV X, R1 | R1의 값(B*(D*e – F/G + C))을 X로 이동 |
(4) 3주소 명령어
- 오퍼랜드 3개를 포함하는 명령어 형식으로 레지스터의 주소를 저장하는 명령어 형식이다.
- 보통 주소1과 주소2로 연산을 수행한 후 주소3에 저장하는 것이 일반적이지만 컴퓨터에 따라 주소2와 주소3으로 연산을 수행한 후 주소1에 저장하는 경우도 있다
- 2주소 명령어와는 다르게 원래 자료가 사라지지 않는다
- 다른 명령어들에 비해 프로그램 길이가 짧음 대신 명령어 자체는 길다
- 명령어 하나를 위해 최소 4번의 기억장소에 접근해야 해 수행시간이 길어짐
- 어셈블리 언어로 표현한 예
ADD X, Y, Z : Y번지의 데이터와 Z번지의 데이터를 더해 X번지에 저장하기
< 3주소 명령어를 이용해 X = B * (C + D * E – F / G) 표현하기 >
명령어 | 동작 |
MUL R1, D, E | D와 E를 MUL(곱하기) 연산 후 결과를 R1에 저장 |
ADD R1, C, R1 | R1의 값(D*E)과 C를 ADD(더하기) 연산 후 결과를 R1에 저장 |
DIV R2, F, G | F와 G를 DIV(나누기) 연산 후 결과를 R2에 저장 |
SUB R1, R1, R2 | R1의 값(D*E+C)과 R2의 값(F/G)을 SUB(빼기) 연산 후 결과를 R1에 저장 |
MUL X, B, R1 | B와 R1의 값(D*E+C – F/G)을 MUL(곱하기) 연산 후 결과를 X에 저장 |
3) 명령어 주소 개수에 따른 장단점
(1) 주소 개수가 많은 경우
- 저장할 오퍼랜드의 수가 많아져 명령어가 더 복잡해짐
- 레지스터의 수가 많아져 연산 속도가 빨라짐
- 프로그램이 짧아져 프로그램 당 명령어 수가 감소함
(2) 주소 개수가 적은 경우
- 오퍼랜드의 수가 적어 간단해 명령어 인출과 실행 속도가 높아짐
- 프로그램의 길이가 증가함
< 참조 >
https://syundev.tistory.com/68
https://devkim93.tistory.com/entry/%EB%AA%85%EB%A0%B9%EC%96%B4-%ED%98%95%EC%8B%9D
4. 퀴즈
Q1) SUB X, Y / BRZ 200일 때 200번지로 분기하더라도 X와 Y는 같지 않다. ( O / X )
Q2) 다음 중 서브 루틴에 대한 설명으로 틀린 것을 모두 고르시오. ( )
(1) CALL 명령어를 통해 서브 루틴의 시작 주소로 분기한다
(2) RET 명령어를 만났을 때 호출한 주소 번지부터 다시 실행된다
(3) 만약 200번지에서 CALL 명령어를 만나면 스택에는 201이 저장된다
(4) RET 명령어를 처리하더라도 스택에 있는 주소 번지는 그대로 남아있는다
Q3) 0주소 명령어는 PUSH, POP를 통해 스택에 저장되고 출력된다. ( O / X )
Q4) 다음 명령어는 몇 주소 명령어이고 실행되면 어떤 식이 도출되는가? ( , )
MOV R1, B / DIV R1, C / MUL R1, A / ADD R1, D |
Q5) 명령어 주소 개수에 따른 장단점에 대해 틀린 것을 고르시오. ( )
(1) 주소의 개수가 적을수록 프로그램 길이는 감소한다
(2) 주소의 개수가 많을수록 저장할 오퍼랜드의 수가 많아지면서 명령어가 더 복잡해진다
(3) 주소의 개수가 많을수록 레지스터의 수가 많이지면서 연산 속도가 빨라진다
(4) 주소의 개수가 적을수록 오퍼랜드의 수가 적어져 명령어 인출과 실행 속도가 빨라진다
정답
A1) X
BRZ는 조건 코드가 0일 때 지정 번지로 분기한다. 이때, 조건 코드는 SUB X, Y인데 X – Y = 0일 때만 지정 번지로 분기하기 때문에 X = Y를 의미하기 때문에 X이다.
A2) (2), (4)
(2)은 RET 명령어를 만나면 호출한 주소 번지의 다음 주소부터 다시 실행이 된다. 스택에 주소 번지가 저장될 때부터 호출한 주소의 다음 주소 번지가 저장된다.
(4)은 RET 명령어를 처리하면 동시에 스택에서 주소 번지가 POP을 통해 삭제된다.
(1)과 (2)는 옳은 설명이다.
A3) O
0주소 명령어에서는 스택에 데이터들이 저장되는데 POP을 통해 스택에 저장되고 POP을 하면 출력되면서 스택에서 지워진다.
A4) 2주소 명령어, A * (B / C) + D (식 순서는 상관 X)
명령어 뒤에 오퍼랜드가 2개 있는 것을 보아 2주소 명령어이다.
그리고 첫 명령어부터 순서대로 해석하면 R1에 B를 넣고 R1(B)를 C로 나누고 그 값을 R1에 다시 저장한다. 그리고 R1(B/C)에 A를 곱해 다시 R1에 저장한다. 그리고 마지막으로 R1(B / C * A)에 A를 더하고 또 다시 R1에 넣는다. 그러면 R1은 현재 A * (B / C) + D라는 식을 갖고 있게 된다.
A5) (1)
주소의 개수가 적으면 한번에 처리할 수 잇는 명령을 몇 번에 나눠 처리하기 때문에 명령어 자체의 길이는 짧을지라도 프로그램 길이는 증가한다.
'Study > 컴퓨터 구조' 카테고리의 다른 글
컴퓨터 구조 - MIPS 구조 (0) | 2020.06.12 |
---|---|
컴퓨터 구조 - 캐시 기억장치 (0) | 2020.06.06 |
컴퓨터 구조 - 메모리 구조와 레지스터 (0) | 2020.05.23 |
컴퓨터 구조 - 명령어를 효과적으로 실행하기 위한 기법 (0) | 2020.05.23 |
컴퓨터 구조 - 어셈블리 언어 (0) | 2020.04.18 |
댓글