728x90

소스 코드 파일을 여러개 만드는 이유

- 큰 프로그램을 하나의 코드로 만들 시 -> 복잡, 분량이 너무 큼 -> 작업 불가 -> 논리/기능 단위로 분리

- 라이브러리 활용 : 자주 쓰는 함수를 파일에 모아 여러 프로그램에서 같이 사용

- 소스 코드 + 라이브러리 소스 코드 전체 같이 컴파일은 비효율 적

 

외부 기호 참조 문법 - EXTERN 문법

- EXTERN symbol

- EXTERN 기호는 심벌 테이블에 등록, 외부에서 선언된 기호라 표시

- opcode에 임의의 값을 넣었다가 나중에 다른 파일에서 심벌 테이블을 읽어 대치함.

 

EXTERN 대치 시 주의 사항

- EXTERN 기호가 대치 시 다른 파일의 주소 값을 사용 x

- 모든 파일의 기계어 코드 + 변수 데이터가 결국 하나로 합쳐 바이너리 생성됨

- 코드/데이터 영역 크기 고려 필요

 

오브젝트 파일 Object file

- 모든 소스코드가 매번 컴파일은 비효율 -> 필요한 코드면 컴파일 + 변경 없는 코드는 컴파일 x

-> 변경 없는 파일을 미리 컴파일 해둠

<-> 미리 컴파일 시 변경된 코드와 병합 시 주소 영역 등이 일치 x

- 중간 파일 역활

 

오브젝트 파일로 바이너리 만들기

- opcode는 모두 기계어로 바꿈. 기호 정보는 오브젝트  파일에 기록

- 각 오브젝트 파일의 기호/참조 정보 조합 -> 바이너리 파일 생성

 

링커 Linker

- 오브젝트 파일을 합쳐 바이너리 만드는 프로그램

- 정적 링킹, 동적 링킹

 

링킹 Linking

- 오브젝트 파일 간 기호 참조 정보를 모아 분석, 정리

 

정적 링킹 static linking

- 라이브러리 오브젝트 파일과 프로그램 오브젝트 파일을 합쳐 단일 바이너리 파일 생성

- 링커 동작하기 간단

 

동적 링킹 dynamic linkiing

- 라이브러리 특정 영역을 필요한 순간 재배치하여 프로그램 동작 하는 방식

- 정적 링킹에 비해 바이너리가 작고, 컴파일 빠름

- 구현 어려움

 

오브젝트 형식 설계 시 주의 사항

- 기호 정보와 참조 정보를 어떻게 유지할 것가

- EXTERN은 외부 파일 참조 의미 -> 다른 파일에서 해당 값을 찾지 못할 수 있음 -> 링킹 실패

 

EXPORT 기호를 사용하는 방법 

- 외부에서 사용하는 기호에 EXPORT 선언 키워드 쓰기

- EXTERN은 타 파일 심벌 테이블에서 EXPORT만 찾아 링커 구성

- 오브젝트 파일에 EXPORT 기호만 포함시키므로 간단 <-> 불일치 시 에러 발생, 자유도 저하

 

EXTERN만 사용하는 방법

- EXTERN 만으로 외부 참조 기호를 찾을 수 있도록 링커 설계

- 다른 오브젝트 파일 심벌 테이블에 있는 모든 기호/참조 정보로 본체를 찾아야 함.

 

오브젝트 파일 형식

- 헤더 : 어디에 어떤 심블 테이블이 있는지 표시. 링커는 헤더의 기계어 시작부터 읽고 합쳐 바이너리 완성

- 내부 심벌 참조 테이블 : EXTERN 제외한 모든 기호의 심벌 테이블 정보. 심벌테이블을 오브젝트 파일에 기록한것.

   타 오브젝트 파일의 EXTERN이 참조하는 대상

- 외부 심벌 참조 테이블 : EXTERN 선언 기호 기록. 타 오브젝트 파일의 내부 심벌 참조 테이블에서 주소/값 읽어       

   opcode 인자에 씀

 

오브젝트 파일 형식

 

오브젝트 파일이 서로 참조하는 방법

- 한 오브젝트 파일의 외부 심벌 참조 테이블은 타 오브젝트 파일 내부 심벌 참조 테이블 참조

-> 링커는 모든 오브젝트 파일의 내부 심벌 참조 테이블로 통합 심벌 테이블을 만듬

-> 통합 심벌 테이블에서 각 오브젝트 파일의 외부 심벌 참조 테이블의 기호를 찾아 값/주소를 전달

 

오브젝트 파일 -> 바이너리

- 기계어 코드 : 코드 영역 + 데이터 영역이 위치한 곳

- 기계어 코드 내 심벌이 참조하는 opcode 인자를 심벌 테이블의 값/주소로 대치

-> 바이너리 완성

재배치 relocation

- 링커가 오브젝트 파일을 합칠 때 배치되는 순서

- 이 순서에 따라 기계어 코드에서 참조 주소 절댓값이 변경됨 -> 주소 값을 정해주는 작업

- 오브젝트 파일 = 재배치 가능 파일 형식

- 링커는 주소 절대 값이 바뀌어도 해당 주소 기호를 참조하도록 함

재배치 시 주소 지정 방식

- PC/Reg-PC 연관 주소 지정 방식을 제외한 모든 방식은 메모리 특정 위치를 절대값으로 주소 지정

- 절대 주소 지정 방식은 재배치로 기호/참조 정보의 주소가 바뀔 시 opcode의 주소 영역도 바뀌어야함.

- 연관(상대) 주소 지정 방식은 opcode 주소 영역 수정 필요 x

 

번역

- 코드의 체계가 바뀌는 과정

ex) 어셈블리어 -> opcode, opcode -> 기계어

 

컴파일 compile

- 상위 언어에서 하위 언어로 번역

- 최종 결과는 기계어

 

컴파일러 compiler

- 컴파일 하는 프로그램

 

빌드 build

- 컴파일 + 링킹해서 최종 프로그램을 만드는 전 과정

 

컴파일러 만들기

- 문법 정의가 필요

-> 대표적으로 BNF(backus-naur form) 베커스 나우어 형식

 

BNF

- 문법 체계가 있는 간단한 규칙 표현

 

BNF 예시

- ::= 은 프로그래밍 언어의 =처럼 우변을 좌변에 대입

- |은 또는

- <>는 확장

-> 문장에 대해 BNF로 아래처럼 정의

<문장> ::= <주어> <서술어>.
       | <주어> <목적어> <서술어> .
       | <문장> <접속사> <문장>.

 

BNF 정의 추가

- <>이 없는 경우 종결 기호

-> BNF 모든 규칙은 종결기호로 결과가 나옴

<주어> ::= <명사> <조사>
       | <명사>
      
<서술어> ::= <부사> <동사>
       | <동사>
      
<목적어> ::= <명사> <조사>
      
<명사> ::= 내 | 너 | 그
<동사> ::= 가다 | 오다
<부사> ::= 빨리 | 늦게
<조사> ::= 을 | 를 | 이 | 가
<접속사> ::= 그리고 | 그러나 | 그런데 | 하지만

 

BNF로 만들 수 있는 문장

내가 가다.
내가 오다.
너가 가다.
너가 오다.
그가 가다.
그가 오다.
내가 가다. 그리고 너가 오다. 그러나 그는 가다.

 

BNF 언어 설계

<program> ::= <block-list>
//프로그램은 하나의 블록 리스트

<block-list> ::= <ident>(<ident-list>) {<decl> <statement>}
              | <block-list> <ident> (<ident-list>) {<decl> <statement>}
/*
<ident> : 블록 이름
<decl> : 변수/상수 선언
<statement> : 연산/ 제어부분
*/

<ident-list> ::= <ident>
				| <ident-list>, <ident>

/*
ident-list 예시
       * ,를구분자로 사용
a, b, c, d, .., g
this_is_param
*/

<ident> ::= <ident> <ident-letter>
          | <ident> <digit>
          | <ident-letter>


/*
- ident의 예시
a
abbb
adasfwq53163
*/


<ident-letter> ::= a | b | c | ... | z | A | B | ... | Z
<digit> ::= 1 | 2 | 3 | ... | 9 | 0

<decl> ::= <def-decl> <var-decl>
		| <decl> <def_decl> <var-decl>

<def-decl>  ::= <ident> <number>

<var-decl> ::= <ident-list>;
		| <var-assignment-list>;
/*
  변수 선언부
<ident-list>; -> 변수명만 쓰고 ;로 끝냄
<var-assignment-list>; -> 변수명, 변수명, ... 변수명;
*/

<var-assignment-list> ::= <ident>=<number>
			| <var-assignment-list>, <ident>=<number>
/*
 변수 선언 문법
a=10
a=10, b=20, c=30
*/

<number> ::= <number> <digit>
// number : 십진수의 연속

<statement> ::= <ident>=<expression>	//a=3, c=a+b
            | <ident>(<ident-list>)		//func(), func(a, b, c, d, e)
            | (<statement-list>)
            | if <condition> then <statement>
            | while <condition> do <statement>

<statement-list> ::= <statement>
                  | <statement-list>; <statement>

<ident>=<expression>

<expression> ::= <term>
             | <adding-operator> <term>
             | <expression> <adding-operator> <term>

<adding-operator> ::= + | -

<term> ::= <factor>
        | <term> <multiplying-operator> <factor>

<multiplying-operator> ::= * | /

<factor> ::= <ident>
          | <number>
          | (<expression>)
          
<codition> ::= not <expression>
            | <expression> <relation> <expression>

<relation> ::= = | <> | < | > | <= | >= | ==


/*

if A > B then
C = A - B;
if A <= B then
C = B - A;
위 if문은 어셈블러어로 아래와 같이 컴파일 된다.
*/

if:
CMP A, B
BGT sub_a_b
BLET sub_b_a
sub_a_b:
SUB C, A, B
B end_if
sub_b_a:
SUB C, B, A
B end_if
end_if:
:

 빌드 과정

1. 컴파일러는 BNF 정의에 따라 소스코드 파싱(구문분석)

2. 최적화 된 어셈블리어로 번역 -> 고급언어의 결과 파일

3. 어셈블러가 오브젝트 파일로 변환

4. 링커가 오브젝트 파일 결합 -> 바이너리 완성

300x250
728x90

opcode의 한계

- opcode는 기계어와 1:1 대응 -> 모든 프로그램 작성 가능

- 프로그래밍 언어의 변수, 함수 같은 요소를 못써 과정이 매우 불편

 

어셈블리어

- Assembly language

- opcode보다 상위 프로그래밍 언어

- 어셈블리코드 -> opcode -> 기계어

 

어셈블리어의 추상화

- 추상화 정도가 낮은 경우 -> opcode와 유사 -> 기계어로 바로 번역

 

어셈블러

- asembler

- 에셈블리어를 기계어로 번역하는 프로그램

- 어셈블리어는 어셈블러에 종속됨 -> 에셈블러에 따라 문법이 다름

 

opcode와 어셈블러

- opcode는 cpu 제조사에서 정함 -> 특정 cpu의 opcode는 어셈블러와 상관없이 모두 똑같음.

- 어셈블러 개발사가 어셈블리 문법을 정함.

 

어셈블리어의 복잡도

- 문법의 정의에 따라 복잡 or 단순

- (추상화 수준을 낮춤) 단순 해질수록 opcode와 유사

- (추상화 수준을 높임) 복잡 해질수록 프로그래밍 언어에 가까워지며, 어셈블러 구현 힘듬

 

CPU 확장(데이터 버스를 16비트에서 32비트로)

- 접근 가능 메모리 용량이 32KB(2^16) -> 4GB(2^32)로 증가

- 여유 비트가 증가 -> 다양한 opcode 정의 가능

- 레지스터 확장 가능 : A, B, PC 3개 -> 16개(이 중 4개는 데이터 저장, 연산이 아닌 특수 용도)

 

레지스터 추가

- LR(Link register) : 하위 함수나 보조 루틴에서 작업을 마친 뒤 호출 위치로 복귀해야할때 호출 지점의 위치를 저장

- SP(Stack pointer) : 스택 레지스터 - 현재 사용하는 스택의 메모리 주소

- ST(Status) : 상태 레지스터 - ALU의 연산 결과를 저장하는 레지스터로 연산 결과와 같이 새 opcode에 사용

 

상테 레지스터(Status Register)

- 32비트 중 LSB 방향의 4비트만 사용

- 연산 결과가 32비트를 넘을 시 오버플로(overflow)에 1이 쓰임.

- 덧셈 or 곱셈 연산으로 자리넘김이 발생 시 캐리에 1을 씀.(ALU의 carry out 핀이 직접 연결됨)

- 연산 결과가 0일때 Zero에 1 써짐(ALU 출력 핀 전체가 연결된 32-input-NAND 게이트에 연결)

- 연산 결과가 음수일때 Negative에 1을 쓰기

특수 레지스터와 범용 레지스터

- 레지스터 16개 중 특수 목적의 LR, SP, ST, PC을 제외한 12개 레지스터는 데이터 처리용 

- 범용 레지스터의 이름은 A ~ L

 

어셈블리어 정의

- 이후 고급언어를 다룰것이므로 추상화 저수준 어셈블리어를 다룸

 

이동 명령

- MOV Rd, {Rs | Value}

- Rd : 데이터가 들어갈 레지스터

- Rs : 원본 데이터가 있는 레지스터

- Value : 그냥 값

- 이동 명령은 즉시 주소 지정 방식만 사용하므로 레지스터 이름이나 값을 직접 사용해야함.

*{A | B} 는 A나 B 둘중 하나를 선택

 

산술 명령

- 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지 연산 5가지

- 주소 지정 방식을 어디까지 허용할 것인지 정해야 함

- ADD Rd, R1, {R2 | Value}

- SUB Rd, R1, {R2 | Value}

- MUL Rd, R1, {R2 | Value}

- DIV Rd, R1, {R2 | Value}

- MOD Rd, R1, {R2 | Value}

- 레지스터 끼리 or 레지스터와 값을 계산

- Rd는 값이 저장되는 레지스터

ex) ADD B, C, D => B = C + D

 

* 로드/스토어

로드 : SRAM -> 레지스터

스토어 : 레지스터 -> SRAM

 

로드/스토어 명령

- LDR Rd, { Rs | #Rs | [Rs] | [#RS] | Address | #Address | [Address] | [#Address] }

- STR Rd, { Rs | #Rs | [Rs] | [#RS] | Address | #Address | [Address] | [#Address] }

- 로드/스토어 명령에는 모든 주소 지정방식이 가능하도록 순서대로 지정

1. 레지스터 직접 주소 지정 방식

2. 레지스터-프로그램카운터 연관 직접주소지정방식

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

4. 레지스터-프로그램카운터 연관 간접주소지정방식

5. 단순 직접 주소 지정 방식

6. 프로그램 카운터 연관 직접 주소 지정방식

7. 단순 간접 주소 지정방식

8. 프로그램 카운터 연관 간접 주소 지정방식

 

로드/스토어 명령 예시

1. LDR A, [B] (레지스터 B에 0x2324가 저장 됨)

-> 주소 0x2324의 데이터를 읽어 레지스터 A에 저장

2. STR A, [B] (레지스터 B에 0x2000가 저장 시)

-> 레지스터 A의 값을 B의 값이 주소인 메모리(0x2000 번지)에 저장

 

논리 연산 명령

- AND Rd, R1, {R2 | Value}

- OR Rd, R1, {R2 | Value}

- XOR Rd, R1, {R2 | Value}

- Not Rd, {Rs | Value}

- 논리 연산은 즉시 주소 지정방식만 사용

- R1과 R2/Value을 연산하여 결과를 Rd에 저장

 

비트 시프트 명령

SHL Rd, R1, {Rc | Count}

SHR Rd, R1, {Rc | Count}

- 비트 시프트 명령도 즉시 주소 지정 방식만 사용

- R1의 데이터를 Rc 레지스터 혹은 count 만큼 왼쪽/오른쪽 시프트

 

* 이후 상태 레지스터를 사용하는 명령

 

비교 명령

- CMP R1, {R2 | Value}

- 연산 결과가 상태 레지스터에 저장 -> Rd, Rs 쓰지 않음

- CMP 명령으로 R1-R2가 0이 되거나 음수 인 경우 상태레지스터의 zero/negative 비트가 1이 됨

* SUB 명령 연산 결과에 따라 상태 레지스터는 변하지 않음

 

분기 명령의 종류

- BR { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BSUB { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BEQ { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BGT { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BLT { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BGET { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

- BLET { Reg | #Reg | [Reg] | [#Reg] | Address | #Address | [Address] | [#Address] }

 

분기 명령

- 분기 명령은 프로그램 카운터 레지스터의 값을 바꾸는 명령

 -> 주기억 장치 메모리 주소 만큼 데이터 처리가 필요

 -> 8개 주소 지정 방식 모두 사용

- BR : 조건 없는 분기. 해당 메모리 주소로 PC 값 변경

- BSUB : 분기 전 당시 PC 값을 링크 레지스터에 저장

 * 분기 명령은 함수 호출 등 구현에 자주 사용. 함수 처리 후 원래 위치 돌아갈때 그 원래 위치를 기억(링크 레지스터)

- BEQ : CMP 명령에서 R1, R2가 같을 때 분기 -> Status Reg : Zero bit 1 or Negative Bit 0

- BGT : R1이 R2보다 클때 분기 -> Status Reg : Zero bit 0 and Negative Bit 0

- BLT : R1이 R2보다 작을 때 분기 -> Status Reg : Zero bit 0 and Negative Bit 1

- BGET : R1이 R2보다 같거나 클때 분기 -> Status Reg : Zero bit 1 or Negative Bit 0

- BLET : R1이 R2보다 같거나 작을때 분기 -> Status Reg : Zero bit 1 or Negative Bit 1

 

 

*** 이전의 내용은 opcode 연관 어셈블리어 문법 ****

순수 어셈블리어 문법

- 상수 선언, 변수 선언, 레이블 정의 (분기 문법은 고급 언어에서 구현 예정)

 

상수 선언 문법

- 기호와 값을 정의 -> 어셈블리가 기호를 값으로 변경

- DEF symbol content

- content에 레지스터 이름, opcode, 다른 기호나 주소가 될 수 있음

 

변수 선언 문법

- BYTE symbol 초기값 : 1바이트 선언문

- WORD symbol 초기값: 4바이트 선언문

- STRING symbol "초기값" : 문자열 변수

- 상수 선언은 기호를 content로 변경, 변수 선언은 메모리 특정 위치에 변수 값이 저장

- 변수의 symbol이 변수 값이 저장된 메모리 주소 표현

 

레이블

- symbol:

- 어셈블러가 알아서 해당 위치 주소로 변경

 

어셈블러와 어셈블리어의 발전

1. (최초)기계어로 어셈블러 구현

2. 어셈블러로 어셈블리어 구현

3. 어셈블리어로 어셈블러 구현 ...

 

심벌 테이블(symbol table)

- 변수와 레이블 처리를 위해 어셈블러 수준에서 심벌 테이블을 만들어야 함.

 

심벌 테이블 만들기

- 어셈블리어 코드 한줄씩 읽기 -> 기계어로 변환

- 기호 정보(변수, 레이블) 만남 -> 기호 이름과 주소 오프셋 위치 심벌 테이블에 기록 -> 끝까지 읽어 심벌 테이블 완성

- 심벌 테이블의 참조 정보를 이용해 실제 값/주소로 대치하여 기계어 완성

 

심벌 테이블

- 기호 이름으로 구분 + 대치할 값이나 주소 등록

- 기호를 참조 위치 주소 오프셋은 ref에 기록

- 여러 번 참조 가능하므로 ref가 여려개 일수 있음

심벌 테이블 사용

- DEF symbol content -> content 값 자체로 대치

- [레이블] symbol : ->코드 영역 메모리 주소로 대치

 

메모리 영역 활용과 어셈블러

- BYTE, WORD, STRING으로 선언되는 변수는 메모리의 데이터 영역

- opcode가 어셈블러로 기계어로 번역되는 데이터는 메모리의 코드 영역으로 구분 필요

- 메모리에서 코드 영역과 데이터 영역을 어떻게 배치할 것인지 정책 필요.

 

메모리에 변수 영역 배치 방법

1. 변수 선언부에 두기

- 변수 선언부에 데이터 영역 배치

- 어셈블리어 코드 중간마다 변수 선언 시 코드 영역과 데이터 영역이 섞임 

 

2. 데이터 영역을 한 곳에 모으기

- 코드 영역의 앞이나 뒤 가능

- 코드 끝난 후 데이터 영역 배치시 중간 마다 변수 선언 되어도, 변수 선언 전에 참조되어도 상관 없음

- 변수 선언과 함께 심벌 테이블에 등록 순간에 실제 메모리 주소를 알 수 없다.

-> 코드 영역 번역 후 데이터 영역 할당 완료 후 심벌 테이블의 주소 공간 값 등록

어셈블러 동작

- 상수/변수 선언을 지나 코드 영역 만나면 opcode를 기계어로 번역

- 기호 참조시 심벌 테이블에서 해당 기도의 참조 위치 목록에 opcode의 프로그램 카운터 값을 넣음 

 -> 심벌 테이블 완성 후 참조 위치 목록 찾아 실제 값 넣음

 

two-pass 어셈블러

- 선언이 코드 보다 늦게 해석 -> 코드 해석시 심벌 테이블에 기호 정보가 없어 참조 위치 등록 불가

- 대부분 어셈블러는 두번 해석

- 첫 해석에서 코드는 무시하고, 데이터 정보만 해석하여 테이블 구성

 

two-pass 어셈블러 심벌 테이블 구성

1. opcode 건너 뛸때마다 어셈블러 내부 PC를 opcode 길이 만큼 늘림

2. opcode 건너 뛴 간격 만큼 데이터 영역 주소가 확정 -> 완전한 심벌 테이블

 

two-pass 어셈블러로 해석 예시

DEF   abc   50

BYTE  bbb  0xFF

 

MOV  A, abc

MOV  B, 0x33

 

ADD   C, A, B

STR    C, [bbb]

 

WORD nnn    0x10EF

 

LDR    A, [bbb]

CMP   A, C

BEQ    im_label2

 

im_label1:

LDR   D, #nnn

LDR   E, [#D]

CMP  D, E

SUB   F, D, E

BLET  im_label2

BGT   im_label1

 

im_label2:

SUB   F, E, D

SHR   G, F, 0x4

STR   G, [nnn]

STR   G, [#nnn]

 

첫 해석 후 심벌 테이블

two-pass 어셈블러 첫 해석

1. DEF abc는 값 50을 등록

2. 데이터 영역은 코드 영역 다음에 두므로 BYTE bbb의 주소로 0x44가 등록

3. nnn은 bbb 다음인 0x45로 주소가 등록

4. 레이블 im_label1/2는 코드 영역 주소 그대로 등록

5. 이후 주소, 갑, 해당 기호 참조 주소 기록 필요

* 주의) 명령어도 데이터 공간을 차지하므로 참조 주소의 값이 각 명령어의 시작 주소가 아님

 

심벌 테이블 완성하기

- 명령어는 32비트 -> 4바이트

- 명령어는 아래와 같이 분할되며 심벌 테이블에 참조 주소들이 등록됨

 

two-pass 어셈블러의 두 번째 해석

- 변수, 상수 등 기호 정보는 무시하고 기계어로 번역

- 기호 정보를 사용한 명령어를 만날시 심블 테이블에서 값/주소 찾아 사용

- 심벌 테이블에 없는 기호 사용 -> 에러 발생

어셈블러 처리 후 주소 배치

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

os만들기 - 1. 바이너리 에디터  (0) 2020.07.28
오브젝트 파일 ~ 고급 언어  (0) 2020.05.01
주소 지정방식  (0) 2020.04.29
Nand2Tetris 2 - 불 연산  (0) 2020.04.29
NAND2Tetris 1 - 불 논리  (0) 2020.04.25
728x90

폰 노이만 아키텍처에서 컴퓨터의 동작

- 데이터를 주기억장치에서 R/W 반복

-> 메모리 주소영역에 접근이 중요

but 아래의 회로에선 PC로 SRAM에 순차적으로만 접근 가능 -> 다른 주소 지정 방식 필요

폰 노이만 아키텍처 컴퓨터 회로

 

Opcode의 인자로 SRAM 주소 접근

- LDA 0x50(8비트 opcode 명령과 데이터)을 레지스터 말고 SRAM 주소에 저장

 * PC/SRAM 사이 Mux와 SRAM-레지스터 사이에 4출력 디먹스 사용

 

SRAM의 주소에 접근하기

- Demux(SRAM)에 sel0과 sel1이 둘다 0일때(NOR)

 -> Mux(PC)의 sel에 1 입력되도록 제어기 수정

 => PC가 가리키는 주소 뿐만이 아닌 SRAM에 임의(random) 접근 가능해짐 

 

접근 가능 주소 범위

- 현재 접근 가능 범위는 명령어 영역(8비트)+데이터 영역(8비트)이므로 0x00 ~ 0xFF까지만 가능

- 지금 SRAM은 64KB -> 전체 주소 영역이 0x0000 ~ 0xFFFF으로 전체 주소 접근 불가

 

주기억 장치 전체 주소 접근 방법

1. 데이터 접근의 지역성 이용 

2. 16비트 주소 값을 어드레스 디코더에 직접 입력

 

데이터 접근의 지역성

- 주로 접근하는 데이터는 실행 중인 메모리 위치 주변이 됨

- PC가 가리키는 곳의 근처 데이터를 자주 읽음

 

PC기준 8비트로 접근 가능 범위

- 8비트로 -128 ~ 127까지 가능

ex) PC가 0x3F20가리키는 경우

0x3F12, 0x3F16, 0x3F24, 0x3F28 ... 앞 뒤로 해당 범위 까지 접근가능

 

PC 중심으로 주소 값을 수정할 수 있는 회로

- SRAM DEMUX를 PC 16bit Adder 향해 입력 전달

- 8비트 이상 범위에 접근 불가

 

메모리 전체 주소 지정

- 현재 SRAM 회로 출력은 16비트이나 상위 8비트는 기계어로 사용되어

- 하위 8비트만으로 16비트 메모리 직접 지정이 불가

-> 16비트 출력 값이 모두 SRAM 디코더에 들어가도록 회로 변경이 필요

 => 8비트(기계어) + 8비트(데이터) or 16비트(주소 데이터)

 

제어기 확장

- (기존) 스위치 회로 -> (확장) 비교기 + 보조기억장치 + 8bit SRAM + 제어기 스위치 박스

- 동작

 1. 전원 연결시 보조 기억 장치의 데이터가 제어기 SRAM에 저장

 2. 주기억 장치에서 전달받은 상위 8비트 기계어는 비교기 거쳐 특정 값 출력

 3. 제어기 SRAM의 해당 주소에 저장된 값이 스위치 박스로 전달

 4. 컴퓨터 회로 제어

- 개선 : 스위치 회로를 복잡하게 구성할 필요가 없어짐 

메모리 주소 지정 이유

- 해당 메모리 값을 읽거나 쓰기 위함

 

즉시 주소 지정 방석(immediate addressing)

- 메모리의 주소를 지정하지 않음. 주로 레지스터에 값을 쓸 때 사용.

 

MOV

- move의 약어

- opcode : MOV 레지스터, 상수

- 상수 값을 레지스터에 저장한다.

- MOV A, 0x90 -> 레지스터 A에 0x90을 쓴다.

 

직접 주소 지정 방식(direct addresing)

- 1) PC에 8비트 값을 더하거나 빼서 메모리 주소를 구하거나

- 2) 직접 8비트 주소를 지정하는 방식 

 

단순 직접 주소 지정 방식(simple direct addressing)

- opcode의 인자로 사용한 값을 그대로 메모리 주소로 지정

프로그램 카운터 연관 직접 주소 지정 방식(PC relative direct addresing)

- PC 카운터에 opcode 인자를 더한 값을 주소로 지정

*로드, 스토어

로드 : 주기억장치에서 값을 읽어 레지스터에 저장

스토어 : 레지스터의 값을 주기억장치에 저장

 

opcode 추가

- LDR(Load register) : 레지스터에 값을 로드 

- STR(Store register) : 레지스터에서 값을 스토어

- 프로그램 카운터 연관 직접 주소 지정 방식 : #를 붙임

 

 예시

- LDR A, #0x34(현재 PC 값이 0x0046)

- 레지스터 A에 0x7A번지(0x0034 +0x0046) 데이터가 저장, PC는 0x0046유지

 

레지스터 직접 주소 지정 방식(register direct addressing)

- 레지스터 출력 값을 SRAM 주소로 전달되는 방식

- 레지스터 크기가 16비트로 SRAM의 주소 크기와 같으므로 전체 영역에 주소 지정 가능

- 레지스터에 미리 주소값을 넣어두어야 함.

 

예시

- MOV B, 0x34

- LDR A, B

 

레지스터-프로그램 카운터 연관 주소 지정방식(Register PC relative direct addressing)

- 레지스터와 PC값을 더해서 SRAM 주소 지정

-> PC 중심으로 전체 메모리 영역 접근 가능

 

간접 주소 지정 방식

- 주소 지정을 간접적으로 하는 방식

- 직접 주소 지정 방식으로 메모리에 주소 지정. 그 주소에서 출력된 SRAM 값을 주소로 다시 지정

 

전체 회로도

- 스위치에서 주소 지정 방식 처리가능한 CPU 회로

- 하드웨어를 제어하기 위해 기계어가 나오고 더 편하게 쓰기 위해 opcode가 나옴

 

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

오브젝트 파일 ~ 고급 언어  (0) 2020.05.01
어셈블리어 ~ 심벌 테이블  (0) 2020.05.01
Nand2Tetris 2 - 불 연산  (0) 2020.04.29
NAND2Tetris 1 - 불 논리  (0) 2020.04.25
NAND2Tetris 0 - 소개  (0) 2020.04.25
728x90

* 집에서 작성하다가 임시 저장을 하지 않고 꺼버려 첫 부분을 날려버렸습니다.. 날라간 부분은 대충 pass

 

2진수

 

32비트 컴퓨터

- 한번에 32비트씩 처리

 

2진수 덧셈

 

부호 있는 2진수

- MSB가 1인 경우 음수

반 가산기(Half adder)

- 입력 : a, b

- 출력 : s(합), c(캐리)

- 이전 연산으로부터 자리올림 입력받지 못함

 

 

전 가산기 (Full adder)

- 반가산기 2개와 or게이트로 구현

- 이전 연산으로부터 자리올림 c를 전달음

- 입력 : a, b, c(캐리)

- 출력 : s(합), c(캐리)

 

 

16비트 가산기

- 전가산기 16개를 이음 -> 16비트 수를 덧셈

inc16

- 16비트 이진수에 +1 연산

 

ALU

- 산술 논리 연산 장치

 

Hack ALU

- 입력 : 16비트 입력 2개, 제어 비트(6비트)

- 출력 : 16비트 출력

* 제어비트가 6비트 인 경우 최대 64가지의 연산 가능. Hack ALU는 16가지 연산 가능

https://georgefabish.com/the-alu/

 

- zx가 0이면 x/ 1이면 0 -> nx가 0이면 그대로/ 1이면 부정(y 동일)

- x와 y or/and 연산 후 f에 따라 or/and 선택

- f 결과와 f 결과 부정을 입력으로 받는 먹스 f에 따라 선택 -> out

- 16비트 전체가 0이면(or16way) zr = 0 아니면 1

- out의 최상위 비트가 1이면(음수) ng = 1/ 아니면 0

 * IsNeg 회로 사용 : out[15] & true = neg -> 먹스로 neg가 1이면 true, 0이면 false

 

- 후기

고향에 다녀오면서 잠깐 정리도 못하고 많이 해맸습니다.

확실히 챕터 1과는 다르게 어려웠던 점은

챕터 1의 회로는 그래도 진리표 대로 정리해가면서 구현해 갈순 있었는데

ALU를 구현할때

if zx 인 1 경우를 어떻게하라.. 처럼

조건문을 어떻게 회로상으로 구현해야할지 정말 막막했지만

다행이 다른 분들이 올리신 글보고 많은 참고가 되었습니다.

 

- hdl을 구현할때 게이트만 입력으로 가능한줄 알았는데 true, false도 가능한 점

- 16비트 x와 false 먹스16 연산시 false가 1비트가 아니라 16비트 false로 되서 출력이 되는 점

- 영 여부 확인할때 N way Or 게이트를 사용하면 된다.

- 음수 여부 확인 시 최상위 비트 체크하면 된다

 

이 외에도

Hardware simulator를 사용하면서 자잘한 에러들이 많았습니다.

 

아직 챕터 2장까지 밖에 못했는데 마무리 할수있을지 걱정됩니다 ㅠㅜ

 

참고 사이트

https://github.com/havivha/Nand2Tetris

https://github.com/sake92/nand2tetris

https://georgefabish.com/the-alu/

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

어셈블리어 ~ 심벌 테이블  (0) 2020.05.01
주소 지정방식  (0) 2020.04.29
NAND2Tetris 1 - 불 논리  (0) 2020.04.25
NAND2Tetris 0 - 소개  (0) 2020.04.25
기계어~OPCODE  (0) 2020.04.25
728x90

모든 디지털 장비

- 컴퓨터, 폰, 라우터 등 정보 저장하고 처리하는거 전부다

- 칩 구성은 다 다르지만. 논리 게이트로 만들어짐

 

논리 게이트

- 다른 물질로 만들거나 만드는 방법은 다르더라도 모든 컴퓨터에서 똑같이 논리 연산을 수행

- NAND를 주로 사용

 

불 게이트(Boolean gate)

- 부울 함수를 따름.

 

부울 대수(Boolean Algebra)

- 부울 대수는 Boolean(이진) 값을 처리함

- 2진 입력을 받아 2진 출력을 보냄

 

진리표(Truth Table)

- 입력에 대한 부울 연산 결과를 들을 보여 줌

 

기본 부울 연산자(boolean operator)

- And, Or, Not

 

AND(논리 곱)

- 둘다 1이면 1

 

OR(논리 합)

- 둘중 하나면 1이면 1

 

NOT(부정)

- 1이 입력되면 0, 0이 입력되면 1 -> 반전

 

기본 부울 연산의 수학적 표현

 

불 함수

- 부울 연산자를 조합한 함수

 

불 함수의 예시와 진리표

 

표준 형식(Canonical Representation)

- 위 불 함수의 경우 1인 경우들만 모아 다음의 표준 형식으로 정리할 수 있음.

2입력 부울 함수 정리


논리 게이트

- 게이트는 부울 함수를 물리적으로 구현한 장치

- 스위치 역활을 하는 트랜지스터로 만들어짐

 

기본 논리 게이트

 

조합 논리 게이트

- 기본 논리 게이트를 조합하여 만들 수 있음.

하드웨어 기술 언어

- HDL(Hardware Description Langauge) = VHDL(Virtual HDL)

- 하드웨어 설계자들은 실제 게이트를 조립하지 않고 HDL로 설계함.

- HDL 프로그램을 시뮬레이션에 입력하여 결과를 구함.

 

Xor 게이트 만들기

- Xor(a,b) = Or(And(a,Not(b)), And(Not(A),B))

 

HDL 작성하기

- HDL 칩 정의는 헤더와 파츠 부분으로 나뉨

- 헤더는 칩 인터페이스를 정의 -> 칩의 이름과 입력 출력 핀

- 파츠에서는 저수준 파츠의 구성과 이름 등을 정의함.

 

Vscode Nand2Tetris 하이라이팅 설치

- VScode에서 Nand2Tetris를 위한 문법 하이라이팅 제공하고 있다.

 

 

Xor 게이트 구현

- Xor.hdl : 헤더에 Xor 게이트 칩 인터페이스 정의, Parts 섹션에 파츠 연결관계 정리

- Xor.tst : 하드웨어 시뮬레이터에서 사용할 테스트 데이터

- Xor.out : Xor.tst에 따라 시뮬레이션 테스트 결과 

Nand2Tetris 하드웨어 시뮬레이션 수행 결과

NAND Gate 구현 및 실험

 

먹스(Multiplexor)

- 입력 : a, b 입력과 둘중 하나를 출력으로 보내는 선택 비트 3개로 이루어짐

- 먹스 진리표에 따라 회로를 다음과 같이 정리 할 수 있음.

먹스 시뮬레이션

 

디먹스(DeMultiplexor)

- 입력으로 in과 sel을 받아 sel이 0이면 a, sel이 1이면 b로 보내는회로

 

디먹스 시뮬레이션

16비트 Not

 

And16

 

Or16

 

Mux16

 

Or8way

 

Mux4way16

- 우선 4-way-mux 구현

- 이후 4-way-mux 16개를 이음

 

Mux8way16

- 우선 8-way-mux 구현

- 이후 8-way-mux 16개를 이음

* 이 코드는 동작은 잘하는데 문제는 너무 길다. 다른사람들이 한걸 보니 MUX16을 구현 후 4 입력을 처리해주더라..

 

DMux4Way

 

 

 

DMux8Way

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

주소 지정방식  (0) 2020.04.29
Nand2Tetris 2 - 불 연산  (0) 2020.04.29
NAND2Tetris 0 - 소개  (0) 2020.04.25
기계어~OPCODE  (0) 2020.04.25
ALU~보조기억장치  (0) 2020.04.24
728x90

1. 소개

 

목표

- 컴퓨터가 어떻게 동작하는지

- 문제를 어떻게 처리하는지

- 하드웨어와 소프트웨어를 어떻게 개발하는지

 

객체 지향 언어로 작성한 코드 예시

(아래는 이 책에서 구현하는 Jack이라는 언어를 사용)

class Main {
	function void main(){
    	do Output.printString("Hello World");
        do Output.println(); //new string
        return;
    }
}

 

코드

- 텍스트 파일에 저장된 문자들

 

어떻게 프로그램이 동작할까?

1. 코드를 파싱

2. 의미를 분석

3. 컴퓨터가 이해하는 저급 언어로 변환

 

기계어

- 2진법으로 구성된 추상적인 언어

- 기계어로 코딩하려면 하드웨어 아키텍처에 대해 알아야 함

 

하드웨어 아키텍처

- 레지스터, 메모리, ALU 등 하드웨어 장치들로 구성

 

하드웨어 장치

- 위 하드웨어 장치들은 논리 게이트로 만들어짐.

 

논리 게이트

- AND, NOT, OR, NAND, NOR 등

 

스위치 회로

- 하드웨어 구성에 필요한 스위치에 트랜지스터를 사용

 

우리가 그동안 배운 컴퓨터 시스템은 빙산의 일각이며,

아래의 내용들을 이해해서 프로그램 코딩 구현 뿐만이아니라 하드웨어와 소프트웨어를 다룰수 있게 됨.

=> 이 기술들을 이해할 수 있도록 밑바닥 부터 컴퓨터를 만들어 보자

 

컴퓨터

- 논리 게이트로 만들 수 있음.

 

모듈

- 매우 복잡하니 모듈이란 개념으로 분리해서 다룸

 

추상화

- 예술과 과학 분야 에서 자주 사용

- 생각이나 특정 개채를 분리하기 위한 개념

 

컴퓨터 과학에서 추상화

- 매우 많이 쓰임

- 이 개체가 뭘하는건지를 의미함

- 어떻게 동작하는지 세부적인건 X

=> 사용자들은 어떻게 만들어지는지 몰라도 되고 쓰는 법만 알면 됨.

 

개발자의 추상화

- 하드웨어/소프트웨어 개발자는 인터페이스라 부르는 추상화 작업을 자주 해야함

- 추상화를 한 층 한층하면서 상위 레벨로 올라가 다양한 역활을 하게 됨

 

컴퓨터 시스템 설계 추상화

- 탑다운 방식으로 나타낼 수 있음.

 -> 고 레벨 추상화를 단순화

- 바텀 업으로 나타 낼 수 있음

 ->저 래밸 추상화를 모아 복잡하게 상위로

 

탑 다운으로 보는 학습 내용

- 고급 언어

- 고급 언어 ~ 하드웨어

    -> 고급 언어를 기계어로 변환 과정

-하드웨어 플랫폼

 

고급언어

 

개발자가 개발시 필요한 것

- 고급 언어와 라이브러리

 

예시 do Output.printString("Hello world").

위 코드의 경우 문자열 출력(printString)을 하기위해 이미 구현된 라이브러리를 사용함.

=> OS와 표준 언어 라이브러리가 필요

 

표준 언어 라이브러리는 뭐고, 운영 체제가 어떻게 동작할까?

- 수학 관련 함수

- 메모리 할당 함수

- 입출력 루틴

- 문자열 처리 등이 사용됨.

 

잭(Jack)

- C언어 비슷한 객체지향 언어

 

고급언어 ~ 하드웨어

- 프로그램을 실행하려면 동작하는 컴퓨터 플랫폼(타겟 컴퓨터)의 기계어로 변환해야함

 -> 컴파일

 

컴파일

- 여러 추상화 레이어로 나눌 수 있음

- 컴파일러, 가상 머신, 어셈블러

 

컴파일러가 하는일

- 컴파일러의 변환 작업은 문법 분석과 코드 생성을 수행함.

- syntax analysis : 소스 코드를 분석해서 의미 단위들을 파스 트리(parse tree)라는 데이터 구조로 나눔.

- 파스 트리를 재귀적으로 처리해서 중간 코드 생성

 

중간 코드(Intermdeiate Code)

- 소스 코드를 표현하기 위해 컴파일러나 가상머신에서 내부적으로 사용하는 코드

 

가상 머신(Virtual Machine)

- 스택 구조

- 컴파일러에서 생성한 중간 코드를 어셈블리 프로그램으로 변환

 

어셈블러

- 어셈블리어로 된 프로그램을 이진 코드로 변환

 

하드웨어

 

Hack

- 4시간 만에 만들수 있는 컴퓨터 아키텍처

- 단순하면서도 성능있음.

- 하드웨어 요소로 어떻게 디지털 컴퓨터 설계하는 과정을 이해하는데 사용함.

 

HDL

- Hardware Description Language(HDL)

- 이 언어로 하드웨어 시뮬레이션하여 Hack을 만듬.

 

Hack 컴퓨터

- 구성 : CPU, RAM, ROM, 시뮬레이션 스크린, 키보드 등

- 이 컴퓨터는 논리 게이트를 조합해서 만들며 부울 대수를 따라 동작함.

 

논리 게이트

- 트랜지스터로 만듬.

 

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

Nand2Tetris 2 - 불 연산  (0) 2020.04.29
NAND2Tetris 1 - 불 논리  (0) 2020.04.25
기계어~OPCODE  (0) 2020.04.25
ALU~보조기억장치  (0) 2020.04.24
가산기~주기억장치  (0) 2020.04.24
728x90

제어기

- 컴퓨터회로의 멀티플렉서, 디멀티플렉서, ALU의 ADD/SUB 등 제어가 필요한 부분들이 존재

- 한 곳으로 모은 제어기를 만듬

 

제어기 스위치

- 제어기 스위치를 제어하여 로드/스토어 작업 수행

제어 예시

- PC가 가리키는 SRAM 값을 레지스터 A에 저장

  - SRAM MUX SEL : 0 0[보조 기억장치 선택]

  - SRAM DEMUX SEL : 0 0 [레지스터 A 방향 선택]

  - Reg A MUX SEL : 1[SRAM 방향 선택]

  - SRAM RW : 1[읽기 모드]

  - MUL/DIV : 0[상관 x]

  - SUB/ADD : 0[상관 x]

-> 레지스터 A에 값을 저장 = 00001100 = 0x0C

 

 

MUX/DIV와 SUB/ADD 조합에 따른 ALU의 연산

* 덧셈 : 0(MUL/DIV), 0(SUB/ADD)

* 뺼셈 : 0(MUL/DIV), 1(SUB/ADD)

* 곱셈 : 1(MUL/DIV), 0(SUB/ADD)

* 나눗셈 : 1(MUL/DIV), 1(SUB/ADD)

 

기계어

- 컴퓨터 회로의 제어기를 제어하는 2진수 언어

 

위 컴퓨터 회로 기계어 정리

메모리에서 기계어 받는 제어기

- 기계어를 보조 기억 장치로 부터 받을 수 있음

- 코드램 : 제어기 쪽에 연결된 SRAM

- 데이터램 : ALU쪽에 연결된 기존 SRAM

 

 

보조기억장치로부터 기계어를 받는경우/ 데이터를 받는 경우

- 기계어를 데이터램에 입력하지 않도록 해야함

 -> 클록 펄스를 구분해서 입력

- 코드 램에 데이터 입력시 -> 데이터 램의 CLK에 펄스 X 코드램의 CLK 펄스 O

- 데이터 램에 데이터 입력시 -> 데이터 램의 CLK에 펄스 O 코드램의 CLK에 펄스 X

 

컴퓨터 회로 총 정리

데이터의 저장

- 메모리의 하위주소에서 상위주소로 저장

 

리틀 엔디언

- 하위 바이트 부터 저장

 

빅 엔디언

- 상위 바이트 부터 저장

 

컴퓨터가 처리하는 데이터

- 처리 데이터 = 동작 명령어, 계산 데이터

 

하버드 아키텍처

- 명령어(8비트) -> 코드 램에 저장, 데이터(8비트) -> 데이터 램에 저장

=> 분리된 메모리 저장하는 방식

폰 노이만 아키텍처

- 명령어(8)와 데이터(8)를 합쳐(16비트) 같은 메모리에 저장하는 방식

- 메모리는 16비트 데이터를 출력함

- 상위 8비트는 제어기, 하위 8비트는 ALU로 전달

 

하버드 아키텍처와 폰 노이만 아키텍처

- 하버드 아키텍처는 메모리가 분리되어 데이터 입출력과 명령어 처리 동시 수행 가능 -> 빠른 속도

 <-> 메모리가 분리되고 별개의 어드레스 디코더 제어로 회로가 복잡 => 고비용

- 폰 노이만 아키텍처는 램을 하나로 줄였지만 동작방식은 하버드 아키텍처와 비슷

 

16비트 CPU

- 데이터를 16비트 씩 처리 -> 2바이트씩 SRAM 주소를 이동해야함

=> 프로그램 카운터를 2씩 늘려줌

2씩 늘어나는 PC

 

8비트, 16비트, 32비트, 64비트 CPU 구분 기준

- 데이터 버스 폭과 ALU의 데이터 처리 크기

 

 

16비트 CPU 구조

 

OPCODE

- LDA = Load to A

- STA = Store from A

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

NAND2Tetris 1 - 불 논리  (0) 2020.04.25
NAND2Tetris 0 - 소개  (0) 2020.04.25
ALU~보조기억장치  (0) 2020.04.24
가산기~주기억장치  (0) 2020.04.24
메모리~램  (0) 2020.04.23
728x90

가산기의 뻴셈 연산

- 2의 보수를 이용하여 가산기 만으로 뻴셈이 가능

- 덧/뻴셈 선택하는 신호선을 만들고 원래 수 그대로 입력하도록 회로 수정 필요

 

XOR 게이트를 이용한 4비트 2진수 1의 보수 변환

- 12 - 8 시 XOR 게이트를 이용하여 1의 보수로 변환 가능

= 1100 - 0100

= 1100 + 0100의 1의 보수 + 1

 

뼬셈 가능한 8비트 가산기 회로

- SUB/ADD 입력에 따라 0인경우 덧셈, 1인경우 뻴셈하도록 XOR를 이용해 1의 보수 변환

- 2의 보수 변환은 Cin에 SUB/ADD(1)을 전달하여 +1을  수행

산술 논리 연산 장치

- 연산기(논리 연산 장치) : 이전의 덧/뻴셈 연산이 가능한 회로

- ALU(arithmetic logic unit) : 산술 논리 연산 장치. 덧/뺄/곱/나눗셈 수행

 

곱셈 회로

- 소프트웨어적으로 구현 가능하나 디지털 회로로 구현한 것 보다 느림

 

10진수의 곱셈

 

2진수의 곱셈

- 각 비트의 곱셈은 AND 게이트로 구현

4비트 이진수 x 4비트 이진수 곱셈기

나눗셈기

1비트 비교기 회로

 

ALU

= 가산기 + 감산기 + 곱셈기 + 나눗셈기

 

보조기억장치

- 앞서 휘발성인 SRAM 주기억장치와, D-FF 메모리 레지스터를 사용

- 전원이 없어도 데이터가 소멸되지 않는 보조기억장치가 필요

 

천공카드

- 구멍을 뚫어 데이터를 저장하는 종이

- 뚫리면 1, 뚫리지 않으면 0

 

천공카드 리더기(punched card reader)

- 읽기 쓰위치를 닫으면 전자석 동작

- 천공 카드 아래의 접점을 끌어당김 

- 구멍이 뚫린 부분만 접점이 통과하여 연결됨

=> 아래의 경우 00100010(2) -> 34(10)

천공카드를 읽어 연산하는 디지털 회로

- 이전의 입력 스위치 8개 대신 8비트 천공 카드 리더기를 입력으로 받음

- 천공 카드 데이터를 입력 받아 연산할 수 있으나 쓰기는 하지 못함

SRAM 데이터를 천공카드에 저장하는 회로

- SRAM 아래의 DEMUX를 1입력3출력 DEMUX로 변경

- 추가 된 출력을 천공카드 리더기의 입력으로 연결

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

NAND2Tetris 0 - 소개  (0) 2020.04.25
기계어~OPCODE  (0) 2020.04.25
가산기~주기억장치  (0) 2020.04.24
메모리~램  (0) 2020.04.23
인버터~플립플롭  (0) 2020.04.23
728x90

반가산기

- 2진수 1비트 덧셈 연산하는 회로

- 자리 올림을 입력 받지 않아 반쪽짜리 가산기란 의미

전 가산기

- Full Adder

- 자리올림을 포함한 전체 덧셈 회로

- 전 가산기 = 반가산기 2개 + OR 게이트

4 비트 가산기

- 전가산기 4개를 이어 만듬

 A3210  B3210

- 0011 + 1011

    A  B  C

 1. 1+1+0(C) = 0(S)/1(C)

 2. 1+1+1(C) = 1(S)/1(C)

 3. 0+0+1(C) = 1(S)/0(C)

 4. 0+1+0(C) = 1(S)/0(C)

=> 0011 + 1011 = 1110

 

8비트 가산기 기호

 

기억장치와 가산기의 연결

- 가산기를 사용 후 결과를 기억할 수 없음 -> 기억장치와 가산기를 연결

1. 8비트 가산기 입력으로 D 플립플롭 램 연결

2. 램 위에 스위치 연결

3. 입력 A의 플립플롭 위에 멀티플랙서 MUX 추가 -> 스위치 or 가산기 결과 둘 중하나를 선택해서 보냄

2-입력-1-출력-멀티플렉서

- 멀티플렉서(Multiplexor:MUX) : 2개의 입력 신호 중 1개를 선택해서 출력

 

가산기의 계산

- 10 + 4+ 18 + 21 + 36 + 37 + 5의 계산

- 10(A), 4, 18, ..., 5는 입력 B를 통해서 입력

 

1. 처음에는 스위치 A와 스위치 B로 입력

2. 가산기의 계산 결과가 입력 A로 다시 들어감

 가산기 + 기억 장치의 계산 흐름

레지스터

- 연산 장치의 값을 저장하기 위한 작은 메모리

- 중간에 레지스터가 없는 경우 가산기 출력 동시에 바로 입력이되어 잘못된 계산 수행 가능하여 이를 방지

- 레지스터는 플립플롭/SRAM/DRAM 중 가장 빠른 플립플롭으로 만듬

 

2진수의 음수 표현

- MSB를 부호 비트(sign bit)로 사용

- 0110100 : MSB가 0이므로 양수, 0110100(2) = +52(10)

- 1110100 : MSB가 1이므로 음수, 1110100(2) = -52(10)

 

2진수의 뺄셈

- 2진수의 뺄셈 = 2진수 + 2진수의 2의 보수

- 1111 - 0010 = 1101

- 1111 + 1110(0010의 2의 보수) =  1101

=> 뺼셈을 덧셈으로 구현 가능

 

전자석 -> 릴레이 -> 인버터 -> (+피드백 연결) -> 오실레이터 (클럭)

게이트 : 트랜지스터 -> 논리 게이트

기억 장치 : R-S 래치 -> R-S 플립플롭 -> J-K 플립플롭 -> D 플립플롭 -> 1바이트 램 -> 8 바이트 램

              -> 8바이트 플립플롭 램 + 어드레스 디코더 + 쓰기 스위치 + 읽기 버퍼/SRAM/DRAM

연산 장치 : 반 가산기 -> 전 가산기 -> 8비트 가산기

 

 

프로그램 카운터+주기억 장치가 추가 된 회로

- 가산기 + 레지스터 회로는 일일이 계산할 값과 CLK를 넣어야 계산 됨

- 10, 4, 18, 21, 36, 37을 한번에 입력한 후 디지털 회로가 알아서 계산하도록 자동화

-> 프로그램 카운터 + 주기억 장치 추가

 

DEMUX

- demultiplexor)의 약어

- 멀티 플렉서의 반대 동작. 하나의 입력을 여러 곳 중 하나로 출력

 

주기억장치 64KB SRAM

- 64KB 크기 -> 0x0000 ~ 0xFFFF 범위 -> 2^10(키로바이트) * 2^6(64)

  -> 2^16 이므로 어드레스 디코더는 16비트 주소 핀 필요 

- 1바이트(8비트) 입력과 1바이트(8비트) 출력

 

프로그램 카운터

- Program Counter(PC)

- 명령어의 위치(주기억 장치 메모리 주소)를 가리킴

 -> 주기억 장치의 어드레스 디코더와 연결

- 아직 명령어 개념 설명 전이므로 8비트 가산기 계산 결과 값이 저장되는 위치를 가리킴

- 카운터는 1씩 증가 -> 다음 주소를 가리키기위해서

 

프로그램 카운터 전용 16비트 가산기

- CLK가 한번 입력 될때마다 프로그램 카운터 출력 값을 1씩 증가

 

주기억 장치로 PC 입력하기

- 1 + 9 + 10 + 12 + 21 + 40 + 37 연산

1. 위 7개 수를 주기억 장치에 입력 

 - R/W : 0(쓰기 모드)

 - 스위치 8개로 8비트 2진수로 입력

 - 각 수를 입력 할때마다 SRAM, PC에 CLK 입력

 => 7개의 수가 0x0000 ~ 0x0006 까지 SRAM에 저장

2. PC의 CLR 신호에 1을 주어 PC 카운터 저장 값을 0으로 바꿈

 -> PC가 가리키는 주소는 한칸씩 내려감

3. 0x0000을 레지스터 A에 입력하기

 - 2번 단계서 프로그램 카운터 값을 0으로 바꿈 -> 0x0000이 SRAM에 전달

 - R/W에 1로 읽기 상태 + 0x0000(Address Decoder) -> 해당 주소 값이 출력

 - DEMUX의 SEL을 0으로 -> SRAM 출력은 A로 간다 -> 레지스터 A 위 MUX를 SEL 1하여 레지스터 A로 입력시킴

4. 0x0001을 B에 입력하기

 - PC의 CLK가 입력되어 PC가 1 증가

 - ADDRESS DECODER는 0x0001번지 읽음

 - DEMUX SEL을 1로 지정하여 레지스터 B로 전달

 

5. 0x0006까지 연산

 - 레지스터 값을 A+B 연산 후 레지스터 A의 먹스 SEL 0으로 설정하면 연산 결과를 레지스터 A에 저장

 - PC 카운터가 1씩 증가하여 0x0000 ~ 0x0006 까지 값이 출력되며 덧셈 연산

 => 연산 종료 시 PC의 값은 7이 됨.

6. 계산 결과를 다시 주기억 장치에 저장하기

- 0x0007의 값이 레지스터 A에 남음 -> SRAM에다 저장 필요

- SRAM 위에 3입력 MUX 추가하여 레지스터 A와 B의 출력 + 8개 스위치를 받도록 연결

- 3입력 먹스 : 스위치 입력 (0,0), 레지스터 A 출력 (1, 0), 레지스터 B 출력 (0, 1)

- PC가 7을 가리킬 때, SEL0[1], SEL1[0]으로 하여 레지스터 A 값을 SRAM으로 전달

- SRAM의 R/W를 0으로 하여 쓰기 모드시 0x0007에 연산 결과를 저장

로드와 스토어

- 로드 : 주기억 장치 값을 읽어 레지스터 A,B에 옮김

- 스토어 : 레지스터 값을 주기억 장치에 저장

=> 컴퓨터 작업은 로드와 스토어들의 연산

 * 그레픽 카드를 제어하는 주소에 스토어 시 모니터에 그림, 글씨 출력

 * 사운드 카드 제어하는 주소에 스토어 시 소리가 출력

 => 데이터를 스토어하는 위치에 따라 출력 형식이 바뀜

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

기계어~OPCODE  (0) 2020.04.25
ALU~보조기억장치  (0) 2020.04.24
메모리~램  (0) 2020.04.23
인버터~플립플롭  (0) 2020.04.23
디지털 ~ 릴레이  (0) 2020.04.23
728x90

D 플립플롭

- R-S 래치에 인버터를 추가하여 같은 값이 입력 되지 않게 고친 플립플롭

메모리 셀

- 1비트 래치/플립플롭

 

램(RAM)

- 플립플롭을 이어 만든 것

- SRAM : 트랜지스터로 만든 래치 모음

- DRAM : 캐패시터와 트랜지스터를 이어 만든 것

 

D 플립플롭 1바이트 램

- 입력 CLK를 스위치 1개를 연결하여 워드라인(Word Line : WL)이라 하고

- 입력 D에 연결한 스위치 8개를 입력이라 한다.

=> 1바이트를 1워드로 묶어 일괄적으로 클록 공금

=> 0 ~ 255까지 입력 가능

 

 

1바이트 램에 이진수 10000110 저장 순서

 

 

MSB와 LSB

- 디지털 회로에서 1비트 이상 데이터 처리시 어느 신호선이 높은 자리인지 낮은자리인지 정해야 함

- MSB(Most Significant Bit) : 가장 높은 비트 위치

- LSB(Least Significant Bit) : 가장 낮은 비트 위치

=> 10000110에서 LSB는 오른쪽 끝 0, MSB는 왼쪽 끝 1

 

 

 

 

 

 

 

메모리 주소

- 1바이트 크기 램에 데이터를 쓰기 위해 8개 스위치 사용, 2바이트의 경우 스위치 16개, 출력 16개 필요

- 1KB 램의 경우 8192개(2^13) 스위치 필요 -> 1MB는 스위치 100만개 필요 => 불가능

<->

램의 특정 주소에 데이터를 쓰거나 읽기

1. 램 영역을 1바이트로로 나누고 주소 지정

2. 그 주소를 찾아 해당 주소의 메모리 셀이 동작

 

1KB 램의 메모리 주소

- 8,192개의 메모리 셀을 8개로 묶음 -> 1바이트 씩 주소 할당 -> 0 ~ 1023까지 주소 사용 가능

 

D 플립플롭 메모리 셀 회로

- D 플립플롭 회로에 입출력, 셀 선텍, 읽기/쓰기 동작 선택 단자를 추가 한 회로

- SEL에 0이면 값 저장 상태 유지

- SEL이 1이면 읽기/쓰기 동작

  - RW : 0 -> 저장된 값 출력

  - RW : 1 -> 입력된 값 저장

메모리 셀 기호


8바이트 램 구성

- 메모리 셀이 가로 8개 세로 8개 총 64개 구성

- 주소는 0 ~ 7까지. 이진법으로 표현 시 3바이트 필요 -> 어드레스 디코더 입력(a1, a2, a3)이 3개

- 주소 신호선은 각 메모리 셀 선택 단자에 연결

- 1바이트 표현에 8개의 입출력 필요 -> 입력 스위치 8개/ 읽기 버퍼 8개

* DI(data input), DO(data output)

어드레스 디코더

- 램 주소를 지정할때 입력 스위치 갯수를 줄이기 위해 사용

- 현재 주소가 7개 뿐이므로 출력 7개(0 ~ 7), 입력 3개(2^3) 총 10개의 스위치로 주소 지정 가능

- 이 경우 3-입력-8-출력 디코더

 

8바이트 램 0x2번지에 6쓰기

- 6은 0000 0110

DI  0 1 2 3 4 5 6 7

->  0 1 1 0 0 0 0 0

 

8바이트 램 0x2번지 값 출력(읽기)

플립플롭 메모리

- SRAM이나 DRAM 처럼 대용량 주기억장치로 쓰기에는 크고 복잡

-> CPU 내부 레지스터에 사용

 

SRAM, DRAM

- SRAM : 트랜지스터로 래치 만듬

- DRAM : 캐패시터로 만듬

 

휘발성 메모리

- D 플립플롭, SRAM, DRAM

- 크기가 큰 순 : D 플립플롭 > SRAM > DRAM

- DRAM은 캐패시터를 사용하여 D 플립플롭이나 SRAM보다 느리고 전력 소모가 큼 -> 대용량 주기억 장치로 사용

- SRAM -> 캐시 매모리

- D 플립플롭 -> 레지스터

 

전자석 -> 릴레이 -> 인버터 -> (+피드백 연결) -> 오실레이터

트랜지스터 -> 논리 게이트 -> R-S 래치 -> R-S 플립플롭 -> J-K 플립플롭

-> 1바이트 램 -> 8 바이트 램 -> 8바이트 플립플롭 램 + 어드레스 디코더 + 쓰기 스위치 + 읽기 버퍼/SRAM/DRAM

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

ALU~보조기억장치  (0) 2020.04.24
가산기~주기억장치  (0) 2020.04.24
인버터~플립플롭  (0) 2020.04.23
디지털 ~ 릴레이  (0) 2020.04.23
CPU 추가  (0) 2020.04.20

+ Recent posts