어떻게 컴퓨터는 소스코드를 해석하고 작동할까?
컴퓨터가 전기적 신호를 통해 연산하여 작동한다는 것은 많은 사람들이 아는 사실이다.
하지만 컴파일러가 어떻게 소스코드를 해석해서 컴퓨터가 작동하기까지에 이르는지 제대로 이해하는 사람은 많지 않다.
해당 내용은 컴퓨터 구조나 운영체제를 공부하면 배울 수 있는데, 개념 정리도 해볼겸 잘 정리된 내용을 발견해서 발번역해볼까 한다.(물론 내맘대로 번역 ㅋㅋ)
https://www.quora.com/How-is-source-code-translated-into-machine-language?force_dialog=1
물리적 수준(Physical Level)
물리적인 현상의 관점에서 볼 때는 모든 것이 전압[1]으로 요약된다. 전자 회로에서는 기본적으로 다른 전압을 사용하여 전압을 제어 할 수 있게 해주는 트랜지스터라는 편리한 장치가 있다. 이것은 전자를 제어 할 수 있는 전자 스위치이다.
트랜지스터[2]는 G(Gate), S(Source), D(Drain)라고 표시된 와이어를 연결 할 수 있는 3개의 터미널이 있다. G단자에 고전압을 흐르게하면 S단자와 D단자가 전기적으로 연결되어 전류가 흐르게 된다. 그러나 G단자의 전압이 낮으면 S와 D단자가 전기적으로 분리가 된다.[3] 이 트랜지스터의 원리를 이용해 전압을 조작하는 회로를 구축 하게 된다. 트랜지스터를 서로 연결하고 분리할 회로 부분을 체계적으로 선택하여 트랜지스터 간에 흐르는 전압을 조작 할 수 있다.
[1] 전압은 전기장의 특정 위치에 전하를 배치함으로써 생기는 전위 에너지를 측정하는 특별한 방법이다. 고전압은 전하 단위당 높은 전위 에너지가 있음을 의미한다. 고전압을 이해하지 못하겠다면 고에너지를 의미하는것이라 생각하자
[2] 이 예시는 MOSFET라는 특정 유형의 트랜지스터에 대한 애기이다.
[3] 이 설명은 MOSFET가 어떻게 작동하는지 물리적 방정식을 지나치게 단순화한 표현이다. 하지만 이러한 전압 스위치 개념은 회로를 구축하는 방법을 개념화하여 이해하는데 도움이 된다.
논리적 수준(Logical Level)
이제 추상화 계층에 대하여 다뤄보자. 컴퓨터(또는 다른 모든 디지털 장치)에서 높은 전압을 전달하는 것은 True, 낮은 전압을 전달하는 것은 False임을 나타낸다고 생각 할 수 있다. 우리는 물리적 수준에서 트랜지스터 회로를 사용하여 논리 게이트라는 장치를 만들 수 있었다. 논리적 AND, 논리적 OR, 논리적 NOT은 개념을 나타내는 물리적 장치일 뿐이다. 이러한 장치가 정의 됨으로써 수학적 논리에 통한 논리 방정식을 세워 회로를 구성 할 수 있게 된다.
이것은 트랜지스터를 사용하여 논리적 AND, OR, NOT 게이트를 구성하는 다이어그램이다. 이중 파란색 선은 트랜지스터를 나타내고 구불구불한 선은 저항을 나타낸다. 예를 들어 NOT장치에서 a부분에 높은 전압(True)를 적용하면 F부분에 낮은 전압(False)가 발생하고, a부분에 낮은 전압(True)를 적용하면 F부분에 높은 전압(True)가 발생하게 될 것이다.
우리는 AND 게이트, OR 게이트, NOT 게이트를 수많은 방법으로 결합하여 참, 거짓 신호를 새로운 참, 거짓 신호로 변환 할 수 있다. 따라서 논리 게이트를 사용하여 참과 거짓을 조작하는 이 아이디어로 우리는 게이트의 입력을 설정하고 다른 쪽에서 나오는 것을 보고 출력 여부를 확인하는 것만으로 사물이 참인지 거짓인지를 계산할 수 있는 회로를 구축 할 수 있다.
전압으로 표현되는 이 단순한 on/off시그널로부터 우리는 산술을 표현할 수 있는 기본 시스템을 구성 할 수 있다. 우리는 고/저 전압의 설정을 통해 2개의 가능한표현(true, false)만 있기 때문에 10진법 숫자시스템 대신 2진법 숫자 시스템을 이용한다.[1] 이제 우리는 true 시그널을 숫자 1, false 시그널을 숫자 0이라고 생각하자. 트랜지스터를 나란히 이제 우리는 AND, OR, NOT 게이트를 창의적인 방식으로 결합하여 덧셈, 뺄셈 등을 수행할 수 있는 새로운 장치를 만들 수 있다. 실제로 우리에게 가장 필요한 연산은 덧셈이다. 뺄셈은 음수를 더하는 것[2], 곱셈을 덧셈을 반복하는 것[3], 나눗셈은 뺄셈을 반복하는 것[4]으로 구현 할 수 있기 때문이다.
[1] 이진수는 십진수의 산술과정과 크게 다르지 않다.
[2] 하드웨어를 사용하여 음의 이진수를 나타내기 위하여 2의 보수 개념을 이해해야 한다.
[3] 실제로 곱셈은 반복되는 덧셈보다는 보다 복잡하게 구현된다. 곱셈이 빠르게 작동 하기 위해서 반복되는 작업을 최소화 하기 때문이다.
[4] 이진수를 사용한 반복 뺄셈은 나머지가 있는 나눗셈에서만 작동한다. 결과적으로 제한된 양의 이진수를 사용하여 분수를 나타내는 것은 상당히 어려운 문제이다.
연산결과 저장
우리는 아직 CPU수준에 도달하지 않았다. 이제 우리는 상태와 메모리라는 개념을 알아야 한다. 즉 전처리/산술 계산의 결과를 기억 할 수 있는 장치를 구축해야 한다. 어떤 계산의 결과를 나중에 다시 사용 할 수 있도록 저장할 수 있어야한다.
우리는 기억할 수 있는 기능을 가진 장치가 필요하다. True/False로 출력되어진 값 뿐만 아니라 지금까지 입력된 값들에도 의존하는 장치가 필요하다. 예를 들면 더하기를 하는 장치를 만들었을때 3 + 5 = 8이라는 결과를 내게된다. 그런데 3 + 5 + 10이라는 연산을 하고싶다면, 중간에 결과물을 저장하고 배치하는 과정이 필요한 것이다. 3 + 5 + 10 = 8 + 10 = 18 이런 식으로 말이다. 이러한 개념을 래치 장치라고 한다. 래치[1]는 마지막 입력을 기억하고 다른 것으로 변경할 때까지 해당 값을 영원히 계속 출력하는 논리 게이트 배열이다. 이 래치 속성을 사용하여 산술/논리 계산을 수행할 뿐만 아니라 해당 계산을 기억하고 나중에 계산할 때 결과를 사용 할 수 있는 회로를 구축 할 수 있다.
이제 메모리 장치를 통해 상태가 시간이 지남에 따라 지속되고 변경 될 수 있으므로 이러한 모든 계산을 동기화 할 방법이 필요하다. 해당 디지털 전자 장치가 전압 신호를 사용하여 매번 연산을 수행하는 행위를 클록이라고 한다. 클록 신호[2]는 높은전압과 낮은 전압 사이에서 매우 빠르게 진동하지만 매우 규칙적인 간격으로 진동하는 전압이다. 우리는 글로벌 클록 신호를 따라 동기화 하도록 논리 회로를 설계하고 클록이 낮음에서 높음으로 전환될 때마다 여러단계의 계산에서 다음 단계를 제공 할 수 있다.
이제 클럭 신호를 따라 동기화하는 진보된 래치장치를 만들 수 있게 되었다. 우리는 이를 플립플롭(flip-flop)이라고 부른다. 플립플롭은 래치와 같은 결과를 기억할 수 있지만 클럭 신호가 Low에서 High로 상승할 때만 기억한다. 이렇게 하면 여러단계 계산의 각 단계를 클록 신호와 동기화 할 수 있다.
[1] 특히 래치는 자체 출력을 입력으로 다시 공급하는 여러 부정 논리 게이트로 구성된다.
[2] 비전문가라도 CPU가 얼마나 빠른지 광고하는데 몇 클럭이다라고 하는것을 들은적 있을 것이다. CPU의 클럭 속도는 실제로 이 전역 클록 신호가 높음과 낮음 전압 사이에서 얼마나 빨리 뒤집히는지를 결정한다. 하지만 클럭 속도는 CPU성능의 유일한 지표는 아니면 CPU가 주어진 프로그램을 얼마나 빨리 실행할 것인지를 결정하는 신뢰하는 수치는 아니다.
더 크고 불량한 메모리 장치
우리의 플립플롭 장치는 각각 한번에 하나의 신호만 출력 할 수 있다. 주어진 시간에 플립플롭은 1또는 0값을 가지만 동시에 둘다 가질수는 없다. 가장 의미 있는 숫자를 저장하려면 그보다 더 많은 이진수를 저장할 수 있어야 하므로 레지스터라는 개념을 도입해보자. 레지스터는 한 번에 여러 숫자를 저장할 수 있는 향상된 플립플롭이다. 플립 플롭과 마찬가지로 레지스터는 클록 신호에 의해 동기화되며 입력을 기억할 수 있다. 주요 차이점은 한 번에 둘 이상의 숫자를 기억 할 수 있다는 것이다. 이제 단일 이진수(비트)가 아닌 전체 이진수를 저장 할 수 있다.
이것이 굉장히 멋진일이지만 수백 또는 수천 개의 숫자를 기억하려면 어떻게 해야될까? RAN module[1]에 대한 아이어가 여기서 도출 된다. 램 모듈은 수많은 레지스터와 유사하게 기능한다[2]. 많은 양의 메모리 셀이 모두 한 행에 정렬되어 있는 장치이다. 각 셀에는 ID(주소) 번호가 매개져 있으며 각 셀은 여러 비트[3]로 구성된 단일 숫자를 저장할 수 있다.
RAM 모듈에 숫자를 저장하려면 먼저 셀 주소를 나타내는 이진수를 모듈의 주소 입력에 연결한 다음에 저장하려는 숫자를 모듈의 데이터 포트에 연결하고 모듈의 쓰기 활성화 신호를 보낸다. 쉽게 말해 해당 메모리 주소에 접근해 데이터를 쓰게 신호를 보내는 것이다. 이렇게 하면 주소로 설정한 숫자에 해당하는 메모리 셀에 숫자가 저장된다.
RAM에서 숫자를 로드하려면 메모리 셀의 원하는 주소를 입력해 설정하면 된다.(이때 쓰기 활성화 신호가 저전압으로 설정됨) 해당 셀의 내용을 데이터 포트에서 출력하게 된다.
[2] 실제로는 일반적인 레지스터로 구성되지 않는다.
[3] 여러비트를 의미하는것은 일반적으로 바이트로 알려진 8bit이다.
지금쯤 잊어버렸을지 모르겠지만, 이 모든 것의 기저에는 우리가 실제로 숫자가 존재한다고 "척"을 하고 있다는 점을 명심해야 된다. 실제로는 여러 장치의 레이어에 조작되는 많은 전압이 있으며, 각 레이어는 복잡성과 추상화를 증가 시킨다. 지금 애기하는 것들은 컴퓨터를 사용하는데 인간이 정의하는 일종의 "약속"이다.
기본 프로세서 구축
이제 레지스터와 RAM 모듈 등이 있으므로 레지스터 전송 데이터 경로라는 회로를 만들 수 있다. 레지스터 및 RAN 모듈과 같은 다양한 메모리 지점 사이에서 단계적으로 데이터를 이동 할 수 있는 일부 회로를 의미한다.
위대한 수학자 Alan Turing[1]은 내부 회로를 변경하지 않고도 다양한 작업을 수행하도록 재구성할 수 있는 장치를 상상했다.(또한 각 명령을 단계별로 실행하는것까지 말이다) 기계가 하는 일을 변경하려면 다른 지시를 내리기만 하면 되며 내부 회로 수정이 필요 하지 않은 튜링 머신[3]과 같은 역할을 할 수 있는 레지스터 전송 데이터 경로를 구축해보자.
작성중...