관리 메뉴

클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

명령어 2 - 명령어의 구조 본문

알고리즘 및 자료 관리/컴퓨터 구조 & 운영체제

명령어 2 - 명령어의 구조

huenuri 2024. 10. 15. 04:55

어제 학습하려고 했지만 오늘 새벽에 일어나 공부를 진행해 본다. 명령어의 구조와 주소 지정 방식을 학습하며 명령어의 생김새와 작동 원리를 이해하는 단원이다.

 

지난 시간에 기계어와 어셈블리어의 형태로 명령어를 접해보았다. 아직 기계어와 어셈블리어를 이루는 각각의 명령어를 자세히 들여다보지는 않았다. 이번 시간에 자세히 들여다보며 연산 코드, 오퍼랜드, 주소 지정 방식이라는 개념을 학습해 보겠다.


 

 

 

연산 코드와 오퍼랜드

누군가에게 명령할 때 이렇게 말한다. 컴퓨터 속 명령어도 마찬가지다. 명령어는 무엇을 대상으로 어떤 작동을 수행하라는 구조로 되어 있다. 

 

 

명령어는 연산 코드와 오퍼랜드로 구성되어 있다. 연산 코드는 명령어가 수행한 연산이고, 연산에 사용할 데이터가 저장된 위치를 오퍼랜드라고 한다. 연산 코드는 연산자, 오퍼랜드는 피연산자라고도 부른다.

연산 코드가 담기는 영역을 연산 코드 필드라고 보르고, 오퍼랜드가 담기는 영역을 오퍼랜드 필드라고 한다.

 

 

붉은 글씨가 연산 코드, 검은 글씨가 오퍼랜드이다.

 

 

 

오퍼랜드

오퍼랜드는 값보다는 연산에 사용될 데이터가 저장된 위치를 훨씬 더 자주 저장하기에 주소 필드라고 부른다.

 

 

오퍼랜드의 명령어 안에 하나도 없을 수도, 한 개만 혹은 두 개 또는 세 개 등 여러 개가 있을 수도 있다.

 

 


 

 

 

연산 코드

연산 코드는 명령어가 수행할 연산을 의미하는데 가장 기본적인 연산 코드 유형은 크게 네 가지로 나눌 수 있다. 이 네 가지 유형 각각에 해당하는 대표적인 연산 코드를 알아볼 것이다. 명령어의 종류와 생김새는 CPU마다 다르기 때문에 연산 코드의 종류와 생김새 또한 CPU마다 다르다.

 

 

혼공컴운 심화 자료 깃허브

 

GitHub - kangtegong/self-learning-cs: 『혼자 공부하는 컴퓨터구조 & 운영체제』 (한빛미디어) 심화자료

『혼자 공부하는 컴퓨터구조 & 운영체제』 (한빛미디어) 심화자료. Contribute to kangtegong/self-learning-cs development by creating an account on GitHub.

github.com

 

심화 자료는 여기에 있으니 나중에 참고하며 공부해 봐도 좋을 것 같다.

 

 

 

 

 

스택과 큐

스택(stack)이란 한쪽 끝이 막혀 있는 통과 같은 저장 공간이다. 한쪽 끝이 막혀 있어서 막혀 있지 않은 쪽으로 데이터를 차곡차곡 저장하고, 저장한 자료를 빼낼 때는 마지막으로 저장한 데이터부터 빼낸다. 스택은 '나중에 저장한 데이터를 가장 먼저 빼내는 데이터 관리 방식(후입선출)'이라는 점에서 LIFO(Last In First Out) 자료 구조라고 부른다.

 

이때 스택에 새로운 데이터를 저장하는 명령어는 PUSH, 스택에 저장된 데이터를 꺼내는 명령어는 POP이다. 

 

스택과 달리 양쪽이 뚫려있는 통과 같은 저장 공간을 큐(queue)라고 한다. 큐는 한쪽으로는 데이터를 저장하고, 다른 한쪽으로는 먼저 저장한 순서대로 데이터를 빼낸다. 큐는 '가장 먼저 저장된 데이터부터 빼내는 데이터 관리 방식(선입선출)'이라는 점에서 FIFO(First In First Out) 자료 구조라고 부른다.


 

 

 

CALL과 RETURN은 함수를 호출하고 리턴하는 명령어이다.

 

 


 

 

 

주소 지정 방식

 

그냥 <연산 코드, 연산 코드에 사용될 데이터> 형식으로 명령어를 구성하면 되지 않을까? 의문이 들 수도 있다. 이는 명령어 길이 때문이다. 

 

 

가령 명령어의 크기가 16비트, 연산 코드 필드가 4비트인 2-주소 명령어에서는 오퍼랜드 필드당 6비트 정도밖에 남지 않는다. 즉 하나의 오퍼랜드 필드로 표현할 수 있는 정보의 가짓수는 2의 6승밖에 존재하지 않는다.

 

 

그리고 명령어의 크기가 16비트, 연산 코드 필드가 4비트인 3-주소 명령어에서는 오퍼랜드 필드당 4비트 정도밖에 남지 않는다. 하지만 만약 오퍼랜드 필드 안에 메모리 주소가 담긴다면 표현할 수 있는 데이터의 크기는 하나의 메모리 주소에 저장할 수 있는 공간만큼 커진다.

 

 

예를 들어 한 주소에 16비트를 저장할 수 있는 메모리가 있다고 가정해 보자. 이 메모리 안에 데이터를 저장하고, 오퍼랜드 필드 안에 해당 메모리 주소를 명시한다면 표현할 수 있는 정보의 가짓수가 2의 16으로 확 커질 것이다.

 

 

오퍼랜드 필드에 메모리 주소가 아닌 레지스터 이름을 명시할 때도 마찬가지다. 이 경우 표현할 수 있는 정보의 가짓수는 해당 레지스터가 저장할 수 있는 공간만큼 커진다.

 

첫 번째 그림의 유효 주소는 10번지, 두 번째 그림의 경우 유효 주소는 레지스터 R1이 된다.

 

 

오퍼랜드 필드에 데이터가 저장된 위치를 명시할 때 연산에 사용할 데이터 위치를 찾는 방법을 주소 지정 방식이라고 한다.

 

 

 

즉시 주소 지정 방식

메모리의 크기가 작아지는 단점이 있지만, 연산에 사용할 데이터를 메모리나 레지스터로부터 찾는 과정이 없기 때문에 앞서 설명한 주소 지정 방식들보다 빠르다.

 

 

 

직접 주소 지정 방식

표현할 수 있는 오퍼랜드 필드의 길이가 연산 코드의 길이만큼 짧아져 표현할 수 있는 유효 주소에 제한이 생길 수 있다.

 

 

 

간접 주소 지정 방식

직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓어졌다. 다만 두 번의 메모리 접근이 필요하기 때문에 앞서 설명한 주소 지정 방식들보다 일반적으로 느리다.

CPU가 메모리를 뒤적거리는 시간은 속도가 많이 느리다. 그렇기에 CPU가 메모리 접근을 최소화하는 것이 좋다.

 

 

 

레지스터 주소 지정 방식

 

때때로 연산에 사용할 데이터가 레지스터에 저장된 경우도 있다. 이 경우 레지스터 주소 지정 방식 또는 레지스터 간접 주소 지정 방식을 사용할 수 있다.

일반적으로 CPU 외부에 있는 메모리에 접근하는 것보다 CU 내부에 있는 레지스터에 접근하는 것이 더 빠르다. 그러므로 레지스터 주소 지정 방식은 직접 주소 지정 방식보다 빠르게 데이터에 접근할 수 있다. 다만, 레지스터 주소 지정 방식은 직접 주소 지정 방식과 비슷한 문제를 공유한다. 표현할 수 있는 레지스터 크기에 제한이 생길 수 있다.

 

 

레지스터 간접 주소 지정 방식

유효 주소를 찾는 과정이 간접 주소 지정 방식과 비슷하지만, 메모리에 접근하는 횟수가 한 번으로 줄어든다는 차이점이자 장점이 있다. 메모리에 접근하는 것이 레지스터에 접근하는 것보다 다 느리다고 했듯이, 레지스터 간접 주소 지정 방식은 간접 주소 지정 방식보다 빠르다.


 

 

 

 

단원 마무리하기

 

 

연산 코드 필드에는 명령어가 수행할 내용이 담기고, 오퍼랜드 필드에는 메모리의 주소가 담긴다. 그러니까 메모리의 주소가 담기는 것은 오퍼랜드 필드이다. 난 문제를 풀 때 메모리의 주소뿐 아니라 다른 것도 담기는 줄 알았다.

 

2번의 풀이도 자세히 살펴보면 다음과 같다. 메모리 6번지 속 200이라는 값을 CPU로 가져온다. 레지스터 간접 주소 지정 방식은 연산 코드에 사용될 데이터를 메모리에 저장하고, 그 주소(유효 주소)를 저장한 레지스터를 명령어 오퍼랜드 필드에 명시하는 방법이다. 즉, R1이라는 레지스터에 담긴 메모리 주소를 확인하면 연산 코드에 사용될 데이터를 얻을 수 있다.

R1 레지스터에 담긴 주소는 6번지로, 200을 저장하고 있다. 

 


 

 

 

학습을 마치고

오늘 새벽에 1시간 반 동안 이 단원을 학습해 보았다. 처음 해보는 컴퓨터 구조 공부라서 그런지 내용이 많이 어렵고 이해하기 어려운 것들도 있었다. 그래도 여러 번 반복을 하면 나중에는 분명 전부 이해되는 날이 있을 것 같다.

어젯밤에 졸리기도 해서 목적 파일과 실행 파일의 차이점을 공부하지 않고 넘어갔는데 지금 이 부분을 보충해서 학습일지에 써넣으려고 한다.