no image
[C++] 백준 3단계 - 2739번 문제
문제설명 소스코드 #include using namespace std; int main() { int input; cin >> input; for (int i = 1; i < 10; ++i) { cout
2023.03.20
no image
[C++] 백준 2단계 - 2480번 문제
문제설명 소스코드 #include using namespace std; int main() { int a; int b; int c; int money; cin >> a >> b >> c; if ((a == b) && (a == c)) { money = 10000 + (a * 1000); cout
2023.03.20
no image
[C++] 백준 2단계 - 2525번 문제
문제설명 소스코드 #include using namespace std; int main() { int H; int M; int input; cin >> H >> M >> input; if (M + input > 59) { H = H + ((M + input) / 60); M = (M + input) % 60; if (H > 23) H = H - 24; cout
2023.03.20
no image
[C++] 백준 2단계 - 2884번 문제
문제설명 본인은 맞다고 생각하는데 계속 틀렸다고 나온다면, 아래의 글을 읽는 것을 추천한다. https://www.acmicpc.net/board/view/100873 글 읽기 - ※ 알람 시계 - 지금 막 질문을 올리려는 당신을 위해 댓글을 작성하려면 로그인해야 합니다. www.acmicpc.net 소스코드 #include using namespace std; int main() { int H, M; cin >> H >> M; if (M - 45 < 0) { M = 60 - (45 - M); if (H - 1 < 0) { H = 23; cout
2023.03.19
no image
[C++] 백준 2단계 - 14681번 문제
문제설명 소스코드 #include using namespace std; int main() { int x, y; cin >> x >> y; if (x < 0 && y < 0) { cout 0) { cout
2023.03.19
no image
[C++] 백준 1단계 - 11382번 문제
문제 설명 소스코드 #include using namespace std; int main() { long long a; long long b; long long c; cin >> a >> b >> c; cout
2023.03.19
no image
[컴퓨터 구조] ALU와 제어장치
이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다. ALU CPU 내부에는 ALU와 제어장치 그리고 여러 개의 레지스터가 있다. ALU는 계산을 담당하고, 제어장치는 명령어를 읽어 들이고 해석한다. 레지스터는 CPU 안에 있는 작은 임시 저장장치이다. ALU는 앞서 계산기와 같은 역할을 한다고 했다. 따라서 레지스터를 통해 피연산자를 받아들이고, 제어장치로부터 수행할 연산을 알려주는 제어 신호를 받아들인다. ALU는 레지스터와 제어장치로부터 받아들인 피연산자와 제어 신호로 산술 연산, 논리 연산 등 다양한 연산을 수행한다. 연산을 수행한 결과는 특정 숫자나 문자가 될 수 있고, 메모리 주소가 될 수 있다. 이러한 결괏값은..
2023.03.13
no image
[컴퓨터 구조] 명령어의 구조와 주소 지정 방식
이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다. 연산 코드와 오퍼랜드 명령어는 연산 코드와 오퍼랜드로 구성되어 있다. 연산 코드 오퍼랜드 위 그림의 색으로 칠해져 있는 필드 값, 즉 '명령어가 수행할 연산'을 연산 코드라 하고, 흰색 배경 필드 값, 즉 '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'를 오퍼랜드라고 한다. 후자가 훨씬 더 많이 사용하므로 이를 주소 필드라고 부르기도 한다. 연산 코드는 연산자, 오퍼랜드는 피연산자라고도 부른다. 이를 간단한 그림으로 나타내면 아래와 같다. 명령어는 연산 코드와 오퍼랜드로 구성되어 있다. 연산 코드는 명령어가 수행할 연산이다. 오퍼랜드는 '연산에 사용..
2023.03.11

문제설명

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	int input;
	cin >> input;
	for (int i = 1; i < 10; ++i)
	{
		cout << input << " * " << i << " = " << i * input << endl;
	}
}

문제설명

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	int a; int b; int c;
	int money;
	cin >> a >> b >> c;
	if ((a == b) && (a == c))
	{
		money = 10000 + (a * 1000);
		cout << money << endl;
	}
	else if (a == b)
	{
		money = 1000 + (a * 100);
		cout << money << endl;
	}
	else if (a == c)
	{
		money = 1000 + (a * 100);
		cout << money << endl;
	}
	else if (b == c)
	{
		money = 1000 + (b * 100);
		cout << money << endl;
	}
	else
	{
		if ((a > b) && (a > c))
		{
			money = a * 100;
			cout << money << endl;
		}
		else if ((b > a) && (b > c))
		{
			money = b * 100;
			cout << money << endl;
		}
		else if ((c > b) && (c > a))
		{
			money = c * 100;
			cout << money << endl;
		}
	}
}

문제설명

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	int H; int M; int input;
	cin >> H >> M >> input;

	if (M + input > 59)
	{
		H = H + ((M + input) / 60);
		M = (M + input) % 60;
		if (H > 23) H = H - 24;
		cout << H << " " << M << endl;
	}
	else
	{
		M = M + input;
		cout << H << " " << M << endl;
	}
}

문제설명

본인은 맞다고 생각하는데 계속 틀렸다고 나온다면, 아래의 글을 읽는 것을 추천한다.

https://www.acmicpc.net/board/view/100873

 

글 읽기 - ※ 알람 시계 - 지금 막 질문을 올리려는 당신을 위해

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	int H, M;
	
	cin >> H >> M;
	if (M - 45 < 0)
	{
		M = 60 - (45 - M);
		if (H - 1 < 0)
		{
			H = 23;
			cout << H << " " << M << endl;
		}
		else
		{
			--H;
			cout << H << " " << M << endl;
		}
	}
	else if (M - 45 > 0)
	{
		M = M - 45;
		cout << H << " " << M << endl;
	}
	else if (M - 45 == 0)
	{
		M = 0;
		cout << H << " " << M << endl;
	}
}

문제설명

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	int x, y;
		cin >> x >> y;
		if (x < 0 && y < 0)
		{
			cout << 3 << endl;
		}
		else if (x > 0 && y > 0)
		{
			cout << 1 << endl;
		}
		else if (x > 0 && y < 0)
		{
			cout << 4 << endl;
		}
		else if (x < 0 && y > 0)
		{
			cout << 2 << endl;
		}
}

문제 설명

 

소스코드

#include<iostream>
using namespace std;
int main()
{
	long long a; long long b; long long c;
	cin >> a >> b >> c;
	cout << a + b + c;
}

 

이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다.


ALU

CPU 내부에는 ALU와 제어장치 그리고 여러 개의 레지스터가 있다.

ALU는 계산을 담당하고, 제어장치는 명령어를 읽어 들이고 해석한다. 레지스터는 CPU 안에 있는 작은 임시 저장장치이다.

ALU는 앞서 계산기와 같은 역할을 한다고 했다. 따라서 레지스터를 통해 피연산자를 받아들이고, 제어장치로부터 수행할 연산을 알려주는 제어 신호를 받아들인다.

ALU는 레지스터와 제어장치로부터 받아들인 피연산자와 제어 신호로 산술 연산, 논리 연산 등 다양한 연산을 수행한다.

연산을 수행한 결과는 특정 숫자나 문자가 될 수 있고, 메모리 주소가 될 수 있다. 이러한 결괏값은 바로 메모리에 저장되지 않고, 일시적으로 레지스터에 저장된다.

 

ALU가 받아들이는 정보는 아래와 같다.

  • 레지스터를 통해 피연산자를 받아들이고, 제어 장치로 부터 수행할 연산을 알려주는 제어신호를 받아들인다.
  • 피연산자와 제어 신호로 산술, 논리 연산등 다양한 연산을 수행한다.

 

ALU는 계산 결과와 더불어 플래그를 내보낸다.

이전에 이진수가 양수인지 음수인지 판별할 때 플래그가 이용된다고 언급한 적 있다.

이러한 연산 결과에 대한 추가적인 상태 정보를 플래그(flag)라고 한다.

ALU가 내보내는 대표적인 플래그는 아래와 같다.

이러한 플래그는 CPU가 프로그램을 실행하는 도중 반드시 기억해야 하는 일종의 참고 정보이다.

플래그들은 플래그 레지스터라는 레지스터에 저장된다.

 

ALU가 내보내는 정보는 아래와 같다.

  • 연산 수행 결괏값과 플래그를 내보낸다.
  • 플래그(연산 결과에 대한 추가적인 참고 정보)
  • 연산 수행 결과

 


 

제어장치

  • 제어장치 : 제어 신호를 내보내고, 명령어를 해석하는 부품
  • 제어신호 : 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호

 

제어장치가 받아들이는 정보와 내보내는 정보를 그림으로 나타내면 아래와 같다.

 

제어장치가 받아들이는 정보

  1. 제어장치는 클럭 신호를 받아들인다.
  2. 제어장치는 해석해야 할 명령어를 받아들인다.
  3. 제어 장치는 플래그 레지스터 속 플래그 값을 받아들인다.
  4. 제어장치는 시스템 버스, 그중에서 제어 버스로 전달된 제어 신호를 받아들인다.

1. 클럭 신호를 받아들인다.

클럭이란 컴퓨터의 모든 부품을 일사불란하게 움직일 수 있게 하는 시간 단위이다.

클럭의 주기에 맞춰, 모든 부품이 작동하게 된다. 하지만 모든 부품이 같은 클럭에 작동하는 것은 아니다.

 

2. 해석해야할 명령어를 받아들인다.

CPU가 해석해야 할 명령어는 명령어 레지스터라는 특별한 레지스터에 저장된다.

제어장치는 명령어 레지스터로부터 해석할 명령어를 받아들이고 해석한 뒤, 제어 신호를 발생시켜 컴퓨터 부품들에 수행해야 할 내용을 알려준다.

 

3. 플래그 레지스터 속 플래그 값을 받아들인다.

플래그는 ALU 연산에 대한 추가적인 상태 정보이다. 그렇기에 제어장치는 플래그 값을 받아들이고 이를 참고하여 제어 신호를 발생시킨다.

 

4. 시스템 버스, 그중에서 제어 버스로 전달된 제어 신호를 받아들인다.

제어 신호는 CPU 뿐만 아니라 입출력장치를 비롯한 CPU 외부 장치도 발생시킬 수 있다.

제어장치는 제어 버스를 통해 외부로부터 전달된 제어 신호를 받아들이기도 한다.

 

제어장치가 내보내는 정보

  • CPU 외부에 전달하는 제어 신호
  • CPU 내부에 전달하는 제어 신호

 

CPU 외부에 전달하는 제어 신호

  • 메모리 : 메모리를 읽기, 쓰기
  • 입출력장치(보조기억장치 포함) : 입출력장치 읽기 / 쓰기
제어장치가 CPU 외부에 제어 신호를 전달
제어장치가 CPU 외부에 제어 신호를 전달한다는 말은 제어 버스로 제어 신호를 내보낸다는 말과 같다.

 

CPU 내부에 전달하는 제어 신호

  • ALU : 수행할 연산을 지시
  • 레지스터 : 레지스터 간 데이터 이동, 레지스터에 저장된 명령어 해석

이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다.


연산 코드와 오퍼랜드

 

명령어는 연산 코드와 오퍼랜드로 구성되어 있다.

  • 연산 코드
  • 오퍼랜드

위 그림의 색으로 칠해져 있는 필드 값, 즉 '명령어가 수행할 연산'을 연산 코드라 하고, 흰색 배경 필드 값, 즉 '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'를 오퍼랜드라고 한다. 후자가 훨씬 더 많이 사용하므로 이를 주소 필드라고 부르기도 한다.

연산 코드는 연산자, 오퍼랜드는 피연산자라고도 부른다.

 

이를 간단한 그림으로 나타내면 아래와 같다.

  • 명령어는 연산 코드와 오퍼랜드로 구성되어 있다.
  • 연산 코드는 명령어가 수행할 연산이다.
  • 오퍼랜드는 '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'이다.
  • '연산에 사용할 데이터가 저장된 위치'가 훨씬 많이 쓰이므로 주소 필드라고 하기도 한다.

 

오퍼랜드

오퍼랜드 필드에는 숫자나 문자와 같이 연산에 사용할 데이터를 직접 명시하기보다는, 많은 경우 연산에 사용할 데이터가 저장된 위치, 즉 메모리 주소나 레지스터 이름이 담긴다. 그래서 오퍼랜드 필드를 주소 필드라고 부르기도 한다.

오퍼랜드는 명령어 안에 하나도 없을 수도 있고, 한 개만 있을 수도 있고, 한 개 이상일 수도 있다.

오퍼랜드가 하나도 없는 명령어를 0-주소 명령어,  오퍼랜드가 하나인 명령어를 1-주소 명령어, 두 개인 명령어를 2-주소 명령어, 세 개인 명령어를 3-주소 명령어라고 부른다.

 

연산 코드

연산 코드 종류는 매우 많지만, 가장 기본적인 연산 코드 유형은 아래의 4가지로 나눌 수 있다.

  • 데이터 전송
  • 산술/논리 연산
  • 제어 흐름 변경
  • 입출력 제어

 

데이터 전송

  • MOVE : 데이터를 옮겨라
  • STORE : 메모리에 저장하라
  • LOAD(FETCH) 메모리에서 CPU로 데이터를 가져와라
  • PUSH : 스택에 데이터를 저장하라
  • POP : 스택의 최상단 데이터를 가져와라

 

산술/논리 연산

  • ADD / SUBTRACT / MULTIPLY / DIVIDE : 덧셈 / 뺄셈 / 곱셈 / 나눗셈을 수행하라
  • INCREAMENT / DECREMENT : 오퍼랜드에 1을 더하라 / 오퍼랜드에 1을 빼라
  • AND / OR / NOT : AND / OR / NOT 연산을 수행하라
  • COMPARE : 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라

 

제어 흐름 변경

  • JUMP : 특정 주소로 실행 순서를 옮겨라
  • CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
  • HALT : 프로그램의 실행을 멈춰라
  • CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
  • RETRUN : CALL을 호출할 때 저장했던 주소로 돌아가라
CALL 과 RETURN은 함수를 호출하고 리턴하는 명령어이다.

 

입출력 제어

  • READ (INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
  • WRITE (OUTPUT) : 특정 입출력 장치로 데이터를 써라
  • START IO : 입출력 장치를 시작하라
  • TEST IO : 입출력 장치의 상태를 확인하라

 


 

주소 지정 방식

오퍼랜드 필드에 숫자나 문자와 같이 연산에 필요한 데이터보다는 메모리나 레지스터의 주소를 담는 경우가 많다고 위에서 언급했었다.

그 이유는 가령 명령어의 크기가 16비트, 연산 코드 필드가 4비트인 2-주소 명령어에서는 오퍼랜드 필드당 6비트 정도밖에 남지 않는다.

즉, 하나의 오퍼랜드 필드로 표현할 수 있는 정보의 가짓수는 2⁶가지로 64개 밖에 되지 않는다.

하지만 여기서 오퍼랜드 필드 안에 메모리 주소가 담긴다면 표현할 수 있는 데이터의 크기는 하나의 메모리 주소에 저장할 수 있는 공간만큼 커진다.

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

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

 

연산 코드에 사용할 데이터가 저장된 위치, 즉 연산의 대상이 되는 데이터가 저장된 위치를 유효 주소(effective address)라고 한다. 

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

주소 지정 방식은 아래와 같이 5가지가 있다.

  • 즉시 주소 지정 방식
  • 직접 주소 지정 방식
  • 간접 주소 지정 방식
  • 레지스터 주소 지정 방식
  • 레지스터 간접 주소 지정 방식

 

즉시 주소 지정 방식

  • 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방법
  • 장점 : 데이터의 크기가 작아진다.
  • 장점 : 데이터를 메모리나 레지스터로부터 찾는 과정이 없기에 빠름

 

직접 주소 지정 방식

  • 오퍼랜드 필드에 유효 주소를 직접적으로 명시하는 방식
  • 데이터의 크기는 즉시 주소 지정 방식보다 더 커졌지만, 여전히 유효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어들음

 

간접 주소 지정 방식

  • 직접 주소 지정 방식의 단점을 보안하기 위함
  • 유효 주소의 주소를 오퍼랜드 필드에 명시한다.
  • 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓다.
  • 두 번의 메모리 접근이 필요하기에 느리다.

참고
CPU가 메모리에서 데이터를 찾는 속도는 매우 느리다.

 

레지스터 주소 지정 방식

  • 직접 주소 지정 방식과 비슷하게 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시하는 방법
  • 특징이 모두 직접 주소 지정 방식과 비슷함
  • 메모리보다 레지스터에서 데이터를 찾는 것이 훨씬 빠르므로 직접 주소 지정 방식보다 빠름

메모리와 레지스터
메모리는 CPU 밖에 있고, 레지스터는 CPU 내부에 있다.
따라서 CPU는 레지스터에 접근하는 속도가 훨씬 빠르다.

 

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

  • 연산에 사용할 데이터를 메모리에 저장하고, 그 주소(유효 주소)를 저장한 레지스터를 오퍼랜드 필드에 명시하는 방법
  • 유효 주소를 찾는 과정이 간접 주소 지정 방식과 비슷하지만, 메모리에 접근하는 횟수가 한 번으로 줄어든다는 차이가 있다.
  • 레지스터 간접 주소 지정 방식은 간접 주소 지정 방식보다 빠르다.

 

정리하자면 아래와 같다.

유효 주소 : 연산에 사용할 데이터가 저장된 위치

  • 즉시 주소 지정 방식 : 연산에 사용할 데이터
  • 직접 주소 지정 방식 : 유효 주소(메모리 주소)
  • 간접 주소 지정 방식 : 유효 주소의 주소
  • 레지스터 주소 지정 방식 : 유효 주소(레지스터 이름)
  • 레지스터 간접 주소 지정 방식 : 유효 주소를 저장한 레지스터