728x90
반응형
SMALL
  • 들어가며

"명령어가 어떻게 생겨야 명령어 파이프라이닝에 유리할까요?"

[연산 코드] [오퍼랜드]

  • 명령어 집합

"CPU는 명령어를 실행한다"

... 근데 이 세상의 모든 CPU가 똑같이 생긴 명령어를 실행할까?

명령어의 세세한 생김새, 연산, 주소 지정 방식 등은 CPU마다 다르다.

x86-64 CPU는 ARM CPU를 이해할 수 없다.

  • 명령어 집합 (구조): CPU의 언어인 셈

명령어가 달라지면 그에 대한 나비효과로 많은 것들이 달라진다

명령어 해석 방식, 레지스터의 종류와 개수, 파이프라이닝의 용이성...

  • 명령어 집합의 두 축: CISC & RISC
    • CISC(Complex Instruction Set Computer)

복잡한 명령어 집합을 활용하는 컴퓨터(CPU)

x86, x86-64는 CISC 기반 명령어 집합 구조

명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용

  • RISC(Reduced Instruction Set Computer)

메모리 접근 최소화(load, store), 레지스터 십분 활용

다만 명령어 종류가 CISC보다 적기에 더 많은 명령어로써 프로그램을 동작

  • 정리

 

728x90
반응형
LIST
728x90
반응형
SMALL

이를 방지하기 위한 분기 예측 (branch predictoin) 기능이 있다.

데이터 위험, 제어 위험 또는 구조적 위험이 발생 시 명령어 병렬 처리를 위한 파이프라이닝이 제대로 동작하지 않는다.

비순차적 명령어 처리를 통해, 순차적으로 명령어를 처리할 시 발생할 수 있는 오류를 방지할 수 있다.

예를 들어 3번이 맨 마지막에 처리됨으로 인해 M(100)과 M(101)의 값이 결정된 이후에 M(102)의 결괏값을 도출해낼 수 있다.

 

 

728x90
반응형
LIST
728x90
반응형
SMALL

들어가며

- 클럭

- 코어 & 멀티 코어

- 스레드 & 멀티 스레드

CPU의 속도를 빠르게 만들어보자

1. 컴퓨터 부품들은 '클럭 신호'에 맞춰 일사불란하게 움직인다.

2. CPU는 '명령어 사이클'이라는 정해진 흐름에 맞춰 명령어들을 실행한다.

-> 클럭 신호를 빠르게 반복된다면 명령어 사이클도 빠르게 반복될 것이라는 기대를 할 수 있다. 

클럭 속도

- 클럭 속도: 헤르츠(Hz) 단위로 측정

- 헤르츠(Hz) : 1초에 클럭이 반복되는 횟수

- 클럭이 "똑-딱-" 하고 1초에 한 번 반복되면 1Hz

- 클럭이 1초에 100번 반복되면 100Hz

클럭 속도를 늘리면 꼭 속도가 빨라질까? 필요 이상으로 클럭을 높이면 발열이 심각해짐

코어와 멀티 코어

- 클럭 속도를 늘리는 방법 이외에는?

- 코어 수를 늘리는 방법 ("듀얼 코어", "멀티 코어" ...)

- 스레드 수를 늘리는 방법 ("멀티 스레드" ...)

예) intel CORE - 8core, 16Thread

코어(Core) 란?

- 현대적인 관점에서 "CPU"라는 용어를 재해석 해야 함

- '명령어를 실행하는 부품'?

- 전통적으로 '명령어를 실행하는 부품'은 원칙적으로 하나만 존재

- But 오늘날 CPU에는 '명령어를 실행하는 부품'이 여러 개 존재

- '명령어를 실행하는 부품'을 코어라는 용어로 사용

코어를 두 개, 세 개, 100개 늘리면 연산 속도도 그에 비례하여 빨라지나요? 꼭 코어 수에 비례하여 증가하지는 않습니다. 조별과제를 예로 들면 4명이 한 프로젝트를 맡는다고 해서 더 빨리 프로젝트가 완료되는 것은 아니다. 코어마다 처리할 연산이 적절히 분배되지 않는다면 CPU 속도를 늘리지 못한다.

스레드란 '실행 흐름의 단위'

1코어 1스레드 CPU도 여러 소프트웨어적 스레드를 만들 수 있다.

멀티 스레드 프로세서를 실제로 설계하는 일은 매우 복잡하지만, 가장 큰 핵심은 레지스터

 

728x90
반응형
LIST
728x90
반응형
SMALL

정해진 흐름대로 명령어를 처리해야지! 

CPU                          <-                                    메모리

인터럽트 (잠깐만!)

 

명령어 사이클

프로그램 속 명령어들은 일정한 주기가 반복되며 실행

이 주기를 명령어 사이클이라고 함

 

메모리에 저장된 명령어를 실행하려면?

cpu <-(인출)- 메모리

 

인출 사이클: 가장 먼저 CPU로 갖고 와야 한다

실행 사이클: 갖고 왔으면 실행해야 한다

 

명령어는 인출 - 실행 - 인출 - 실행 - ...

반복되면서 실행됩니다.

 

그런데 CPU로 명령어를 가지고 와도 바로 실행이 불가능한 경우도 있다.

 

메모리의 접근이 더 필요한 경우 간접 사이클이 추가될 수 있다.                      

 

이와 같은 정해진 흐름을 끊는 것이 바로 인터럽트이다. 방해하는 신호이다.

 

인터럽트

인터럽트 (interrupt) : 방해하다, 중단시키다

'CPU가 꼭 주목해야 할 때', 'CPU가 얼른 처리해야 할 다른 작업이 생겼을 때' 발생

"강대리, 이거 급한 거니까 지금 하던 일 멈추고 이것부터 처리해주게"

 

인터럽트 - 동기 인터럽트 (예외)

              - 비동기 인터럽트 (하드웨어 인터럽트)

"인터럽트의 종류에는 예외와 하드웨어 인터럽트가 있습니다."

대부분은 인터럽트 플래그로 인터럽트를 막을 수 있다.

 

728x90
반응형
LIST
728x90
반응형
SMALL

들어가며

레지스터는 CPU 내부의 작은 임시저장장치

프로그램 속 명령어 & 데이터는 실행 전후로 레지스터에 저장

 

CPU 내부에는 다양한 레지스터들이 있고, 각기 다른 역할을 가진다

 

 

반드시 알아야 할 레지스터

1. 프로그램 카운터 : 메모리에서 가져올 명령어의 주소(메모리에서 읽어 들일 명령어의 주소) - Instruction Pointer (명령어 포인터) 라고 부르는 CPU도 있다.

2. 명령어 레지스터 : 해석할 명령어 (방금 메모리에서 읽어 들일 명령어) - 제어장치가 해석

3. 메모리 주소 레지스터 : 메모리의 주소를 저장 - CPU가 읽어 들이고자 하는 주소를 주소 버스로 보낼 때 거치는 레지스터

4. 메모리 버퍼 레지스터 : 메모리와 주고받을 값 (데이터와 명령어) - CPU가 정보를 데이터 버스로 주고받을 때 거치는 레지스터

5. 플래그 레지스터 : 연산 결과 또는 CPU 상태에 대한 부가적인 정보

6. 범용 레지스터 : 다양하고 일반적인 상황에서 자유롭게 사용

7. 스택 포인터 : 스택의 꼭대기를 가리키는 레지스터로서 스택이 어디까지 차 있는지에 대한 표시

8. 베이스 레지스터 : 기준 주소 저장

 

* 스택 주소 지정 방식 : 스택과 스택 포인터를 이용한 주소 지정 방식

* 변위 주소 지정 방식 : 오퍼랜드 필드의 값(변위)과 특정 레지스터의 값을 더하여 유효 주소 얻기

* 상대 주소 지정 방식 : 오퍼랜드 필드의 값(변위)과 프로그램 카운터의 값을 더하여 유효 주소 얻기

* 베이스 레지스터 지정 방식 : 오퍼랜드 필드의 값(변위)과 베이스 레지스터의 값을 더하여 유효 주소 얻기

 

 

1~4번 순서

* 프로그램 카운터가 1 증가하는 것은 프로그램을 순차적으로 실행할 수 있는 원리가 됩니다.

순차적으로 실행 흐름이 끊기는 경우 발생시 다음과 같이 해결합니다.

1) 특정 메모리 주소로 실행 흐름을 이동하는 명령어 실행 시 

(e.g. JUMP, CONDITIONAL JUMP, CALL, RET)

2) 인터럽트 발생 시 

3) ETC...

 

 

 

 

 

728x90
반응형
LIST
728x90
반응형
SMALL

ALU는 계산하는 장치

제어장치는 제어 신호를 발생시키고 명령어를 해석하는 장치

 

ALU - 받아들이는 정보

계산을 하기 위해서는 피연산자의 수행할 연산이 필요

 

레지스터 -> (피연산자) -> | ALU  | -> (플래그) -> 플래그 레지스터

제어장치 -> (제어신호) -> |           | -> (결괏값) -> 레지스터 

 

플래그 레지스터 - 음수, 0 (부가 정보가 담김), 연산 결과가 결과를 담을 레지스터에 비해 너무 클 시 오버플로우라고 하는데, 오버플로우 발생 시 이를 표시하여 나타낸다.

 

 

ALU - 내보내는 정보

플래그 종류 의미 사용 예시
부호 플래그 연산한 결과의 부호를 나타낸다 1은 음수, 0은 양수를 의미
제로 플래그 연산한 결과가 0인지 여부를 나타낸다 1은 0, 0은 0이 아님
캐리 플래그 연산 결과 올림수나 빌림수가 발생했는지 나타낸다. 1은 올림수 또는 빌림수, 0은 발생하지 않음
오버플로우 플래그 오버플로우가 발생했는지를 나타낸다. 1은 오버플로우, 0은 발생하지 않음
인터럽트 플래그 인터럽트가 가능한지를 나타낸다. 인터럽트는 04-3절에서 설명한다. 1은 인터럽트 가능, 0은 인터럽트 불가능
슈퍼바이저 플래그 커널모드로 실행 중인지, 사용자 모드로 실행 중인지를 나타낸다.  1은 커널모드 실행 중, 0은 사용자 모드 실행 중

 

 

플래그 레지스터

 

부호 플래그 | 제로 플래그 | 캐리 플래그 | 오버플로우 플래그 | 인터럽트 플래그 | 슈퍼바이저 플래그 |

1                  0                  0                  0                             0                        0

 

 

제어장치

 

 

클럭 신호

시간이다.

일정한 박자에 맞춰서 똑딱 똑딱 발생하는 신호다.

 

 

728x90
반응형
LIST
728x90
반응형
SMALL

C 언어 컴파일 과정

 

test.c

 

전처리기(preprocessor) 

 

test.i

 

컴파일러(compiler)

 

test.s

 

어셈블러(assembler)

 

test.o

 

링커(linker)

 

test.exe

 

 

전처리 과정 (preprocessor)

- 본격적으로 컴파일하기 전에 처리할 작업들

- 외부에 선언된 다양한 소스 코드, 라이브러리 포함

- 프로그래밍의 편의를 위해 작성된 매크로 변환

- 컴파일할 영역 명시

 

컴파일 과정 (Compiling)

- 전처리가 완료 되어도 여전히 소스 코드

- 전처리 완료된 소스 코드를 저급 언어(어셈블리 언어)로 변환

 

어셈블 과정 (assembling)

- 어셈블리어를 기계어로 변환

- 목적 코드(object file)를 포함하는 목적 파일이 됨

 

C 언어 컴파일 과정

- 목적 파일 vs 실행 파일

  - 목적 파일과 실행 파일은 둘 다 기계어로 이루어진 파일

  - But, 목적 파일과 실행 파일은 다르다.

  - 목적 파일은 링킹(linking)을 거친 이후에야 실행 파일이 된다

 

링킹 과정 (linking)

컴파일 된 목적 파일들은 독립적으로 실행될 수 없다.

따라서 목적 파일들을 서로 연관지어서 실행파일을 만든다.

실행파일이 최종적으로 완료되면 프로그램 실행이 가능하다.

728x90
반응형
LIST
728x90
반응형
SMALL

기계어, 어셈블리어

저급 언어로 변환

 

명령어: "학생들, 다음 주까지 과제를 제출하세요."

 

 

명령어의 구조

- 연산코드: 수행할 연산

- 오퍼랜드: 연산에 사용될 데이터 혹은 연산에 사용될 데이터가 저장된 위치

 

 

오퍼랜드

- 연산에 사용될 데이터

- 연산에 사용될 데이터가 저장된 위치 (주소필드)

 

 

연산코드

- 데이터 전송

MOVE: 데이터를 옮겨라

STORE: 메모리에 저장하라

LOAD: 메모리에서 CPU로 데이터를 가져와라

PUSH: 스택에 데이터를 저장하라

POP: 스택의 최상단 데이터를 가져와라

 

- 산술/논리 연산

ADD / SUBTRACT / MULTIPLY / DIVIDE : 덧셈 / 뺄셈 / 곱셈 / 나눗셈을 수행하라

INCREMENT / DECREMENT : 오퍼랜드에 1을 더하라 / 오퍼랜드에 1을 빼라

AND / OR / NOT: AND / OR / NOT : 연산을 수행하라

COMPARE : 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라

 

- 제어 흐름 변경

JUMP : 특정 주소로 실행 순서를 옮겨라

CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라

HALT : 프로그램의 실행을 멈춰라

CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라 

RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라

 

- 입출력 제어

READ(INPUT) : 특정 입출력 장치로부터 데이터를 읽어라

WRITE(OUTPUT) : 특정 입출력 장치로 데이터를 써라

START IO : 입출력 장치를 시작하라

TEST IO : 입출력 장치의 상태를 확인하라

 

 

명령어 주소 지정 방식

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

- 명령어 주소 지정 방식 (addressing modes) : 

연산에 사용할 데이터가 저장된 위치를 찾는 방법

유효 주소를 찾는 방법

다양한 명령어 주소 지정 방식들

 

- 즉시 주소 지정 방식 (immediate addressing mode)

연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시

가장 간단한 형태의 주소 지정 방식

연산에 사용할 데이터의 크기가 작아질 수 있지만, 빠름

 

[연산 코드][연산에 사용할 데이터]

 

- 직접 주소 지정 방식 (direct addressing mode)

오퍼랜드 필드에 유효 주소 직접적으로 명시

유효 주소를 표현할 수 있는 크기가 연산 코드만큼 줄어듦

 

- 간접 주소 지정 방식 (indirect addressing mode)

오퍼랜드 필드에 유효 주소의 주소를 명시

앞선 주소 지정 방식들에 비해 속도가 느림

 

- 레지스터 주소 지정 방식 (register addressing mode)

연산에 사용할 데이터가 저장된 레지스터 명시

메모리에 접근하는 속도보다 레지스터에 접근하는 것이 빠름

 

- 레지스터 간접 주소 지정 방식 (register indirect addressing mode)

연산에 사용할 데이터를 메모리에 저장

그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시

 

 

 

 

 

 

 

 

 

 

728x90
반응형
LIST

+ Recent posts