* 2019.3.19
  * 배경 지식(?) 및 1,2단원 정리
   * 현대 컴퓨터의 대부분은 폰 노이만 구조를 따르고 있음
    * 프로세서(ALU,레지스터), 컨트롤 유닛(CU), 메모리(RAM), 외부 대용량 저장소(HDD,SSD), I/O
   * 컴퓨터 살 때 뭐 사죠?
    * CPU, RAM, 그래픽카드, 모니터/마우스/키보드, 하드디스크, SSD 등등
    * 기본적인 구조인 프로세서 <-> 메모리를 어떻게 구현했는지
   * 컴퓨터 구조에 대한 간단한 설명
    * CPU,Memory, I/O Devices가 있고 각각이 Data bus, Control Bus, Address Bus가 연결하고 있음
   * 메모리 계층
    * (레지스터) -> 캐시 -> 메인 메모리(RAM) -> 보조 메모리(HDD,SSD)
   * 명령어 실행 과정
    * (명령어 인출 -> 실행) 반복한다
    * 파이프라이닝이나 인터럽트 등의 이유로 여러 과정이 추가되거나 과정이 나눠질 수 있지만, 기본적으로 이렇다
  * 1단원
   * 코드 -> (컴파일러) -> 어셈블리 코드 -> (어셈블러) -> 기계어
   * 어셈블리어와 기계어는 1:1로 매칭됨
   * 2진수 표현
    * 어차피 논리회로 때 다 배웠을 것이다
    * 오버플로우에 대한 얘기 -> MSB로 들어오는 캐리와 나가는 캐리가 다를 때
  * 2단원
   * 배경 지식 할 때 했던 것들
   * 파이프라인
    * 앞서 진행했던 명령어 실행 과정을 여러 개로 나눌 수 있음
    * 빨래통->세탁기->건조기->옷장을 예로 들어 설명
    * x86은 명령어 실행 단계를 6단계로 나눌 수 있는데, 각각의 실행 단계를 '''물리적으로 분리할 수 있음'''
    * 각각의 단계를 병렬적으로, 6개의 명령어를 병렬적으로 동시 수행하여 속도/클럭 속도를 대략 6배 정도 증가시킬 수 있음
   * 슈퍼스칼라 (멀티코어 프로세서)
    * 파이프라이닝 6단계 중 한 단계가 오래 걸린다면, 그것 때문에 클럭 속도를 늦추는 건 비효율적임
    * 예를 들어 실행 단계에서 두 클럭 이상의 시간이 걸린다면, 실행 단계를 처리하는 모듈을 추가로 배치해서 속도를 올릴 수 있음
    * ex) 실행 단계 처리하는 하드웨어 1에는 홀수 번째 명령어만 보내고, 짝수 번째는 하드웨어 2로 보냄
   * 메모리 읽기
    * 1단계: 주소 버스에 읽고자 하는 주소가 올려짐
    * 2단계: 메모리의 read 플래그가 0으로 변경됨
    * 3단계: data bus에 값이 읽힘
    * 4단계: 메모리의 read 플래그가 1로 변경됨
   * 캐시 메모리
    * 캐시 메모리 -> 메인 메모리(RAM) -> 보조 메모리(HDD,SSD)
     * 오른쪽으로 갈수록 용량 당 가격(현금)이 저렴해지고, 속도가 느려짐
     * 1개의 프로그램을 실행하는 상황을 가정해보자
      * 프로그램 전체가 메인 메모리에 올라가고, 일부를 캐시에 가져옴
      * 찾고자 하는 데이터가 있으면 먼저 캐시에 있는지 보고, 아닐 때 메인 메모리에 접근해서 가져옴
      * 캐시에 접근할 때는 1클럭만에 접근할 수 있지만, 메인 메모리에 접근할 때는 수십 클럭이 걸림
      * 캐시 Hit 비율을 높게 잡는 게 중요하겠죠
 

 * 2019.5.25
  * 12단원
   * float,double 등의 실수 값은 컴퓨터로 어떻게 저장되는가
    * 먼저 10진수를 표현하는 방법으로 접근해보자
     * 123.4567에서 각각의 자리는 10^2, 10^1, 10^0, 10^-1, 10^-2.... 자리다
     * 다음 표현들은 다 같은 값이다
      * 123.4567
      * +1.234567e+02
      * '''+''' '''1.234567''' * 10^'''2'''
     * 마지막 표현 방법으로 수를 표기할 때, 어떠어떠한 정보가 있으면 수를 확정할 수 있을까?
      * 부호
      * 유효숫자? 
      * 10의 지수 (exponent)
     * 위 3개의 정보가 필요하다는 것을 알고 가자
    
    * 2진수로 표현한 실수를 보자
     * 2진수 101.1011은 각 자리가 2^2, 2^1, 2^0, 2^-1, 2^-2, 2^-3, 2^-4
      * 값은 4 + 1 + 1/2 + 1/8 + 1/16이 되겠죠?
     * 위에서 했던 10진수 표현과 같이 여러 가지 방법으로 표현해보자
      * 101.1011
      * '''+'''1.'''011011''' * 2^'''2'''
      * 여기서도 필요한 정보는 '''sign, fraction, exponent'''
      * 2진수로 표시하면, 값이 정확히 0이 아닌 경우는 맨 앞의 수가 무조건 1이다
      * 지수는 음수가 될 수 있다
      * 이 3개의 정보를 32비트(float) 또는 64비트(double) 안에 넣는 방법?
     
   * '''IEEE-754'''
    * 위에서 말한, 비트 안에 정보를 저장하는 방법의 표준
    * float
     * 1비트 sign, 8비트 exponent, 23비트 fraction
    * double
     * 1비트 sign, 11비트 exponent, 52비트 fraction

    * float 기준으로 설명해보자
     * 유의할 점
      * exponent는 0 이하의 수일 수 있기 때문에, 비트 10000000이 기준 값(0)이 됨
       * 이 값보다 1씩 작아질수록 exponent가 작아지고, 커질수록 exponent가 커짐
       * ex) 10000011: 지수 3, 01111101: 지수 -2
      * 위에서 언급한 것처럼, 지수 형태로 표현했을 때 맨 앞의 수는 원래 수가 0이 아닌 경우 무조건 1임
       * 맨 앞의 1은 저장할 필요가 없다
       * 0을 저장하는 방법은 뒤에 따로 있음
     * 방법
      * 맨 앞의 1비트에 부호 저장(음수면 1, 양수면 0)
      * 다음 8비트에 지수 저장 (기준:10000000)
      * 나머지 23비트에 소수점 이하의 비트 그대로 저장
     * ex) 3.25
      * 3.75 = 2 + 1 + 0.25
       * 2진수로 11.01  = 1.101 * 2^1
        * 부호비트: 0 
        * 지수비트 10000001
        * 가수비트 101
        * 따라서 float로 표현하면 0 10000001 1010000000000....000
    * '''컴퓨터구조때 다시 배운다아아'''