Scribbling

컴퓨터의 구조 - 6 본문

Computer Science/Computer Knowledge

컴퓨터의 구조 - 6

focalpoint 2021. 9. 5. 16:05

 

1. 어셈블리 언어 (Assembly Language)

컴퓨터는 (혹은 CPU는) 0과 1의 bit로 이루어진 기계어만을 이해할 수 있다. 사람이 기계어를 이용하여 코딩하려면, 무수히 많은 비트 조합을 다 외우고 있어야 할 것이다. 어셈블이 언어는 이러한 비트 조합을 추상화한 언어로, 보다 이해하기 쉬운 니모닉 (Mnemonics)를 통하여 명령어를 작성할 수 있도록 한다.

어셈블러 (Assembler)는 어셈블리 언어로 작성된 코드를 바탕으로 기계어 코드 (Machine Code)로 생성한다.

 

2. 고수준 언어 (High-Level Language)

고수준 언어는 어셈블리 언어보다 더 높은 추상화 단계에서 작동한다. 고수준 언어의 소스 코드 (Source Code)는 컴파일러 (Compiler)라는 프로그램에 의해 실행된다. 컴파일러는 소스 코드를 기계어로 번역 혹은 컴파일 (Compile) 한다. 

여기서 기계어는 특정 기계에서 작동하는 비트 조합이라고 이해하면 된다. 기계어 코드는 목적 코드 (Object Code)로도 불리운다. 참고로, CPU 제조사마다 기계어가 다르다.

- 비구조적 언어: Goto와 레이블을 조합하는 초기적 언어. 

- 구조적 언어: 잘못된 Goto 사용으로 인해 발생하는 스파게티 코드 (Spaghetti Code) 문제를 해결하기 위해 개발된 언어.

 

고수준 언어는 어떻게 동작하는가?

간단히 말하면, 명령어의 토큰화 (Tokenization)과 상태 기계 (State Machine)을 이용한다.

2.1. 정규식

명령어를 토큰화 하기 위해 언어를 지정하기 위한 언어를 정의할 필요가 있다. 정규식 (Regular Expression)은 그러한 역할을 수행한다. 정규식은 패턴 매칭 (Pattern Maching)에서 중추적 역할을 한다.

 

2.2. 파스 트리

일반적으로 컴파일러나 인터프리터는 파스 트리 (Parse Tree)를 구성한다. 이는 명령어 집합을 언어 문법에 맞게 DAG 데이터 구조로 표현한 것이다.

 

3. 컴파일러와 인터프리터

3.1. 컴파일러 (Compiler)

컴파일러는 소스 코드를 기계어로 변환한다.

 

3.2. 인터프리터 (Interpreter)

인터프리터 언어는 기계어를 만들어내지 않는다. 대신 가상 머신 (Virtual Machine)에서 실행된다. 여기서 가상 머신이란, 소프트웨어로 구현된 기계를 의미한다. 일부 인터프리터 언어는 인터프리터에 의해 직접 실행되는 경우도 있으며, 또 다른 인터프리터 언어들은 중간어 (Intermediate Language)로 컴파일되기도 한다.

 

3.3. 컴파일러 VS 인터프리터

- 일반적으로 컴파일된 코드가 기계어이기 때문에 더 빠르게 실행된다.

- 인터프리터 언어는 하드웨어로 구현하기 어려운 기능을 제공할 수 있다.

- 컴파일러는 전체 소스 코드를 명령어 파스 트리로 재구성한다. 반면 인터프리터는 소스 코드의 각 행을 연속적으로 분석하여 실행한다. 

 

3.4. 자바 (JAVA) 

자바는 대표적인 고수준 언어 중 하나이다. 자바는 특이하게도 컴파일과 인터프리터 두 단계를 모두 수행한다. 자바로 작성된 소스 코드는 JavaC (Java Compiler)에 의해 컴파일 되어 기계어로 변환된다. 여기서 변환된 기계어는 Java Virtual Machine (JVM; Java Virtual Machine은 하드웨어가 아닌 소프트웨어로 구현된 기계이다)을 위한 것이다. 여기서 중간 단계의 기계어는 JVM을 위한 기계어이며, JVM은 일종의 인터프리터이다. JVM은 .class 확장자의 중간단계 기계어를 인터프리팅하여 코드가 실행된 하드웨어 플랫폼에서 동작하는 기계어로 다시 변환한다. 이러한 구조 덕분에 자바는 플랫폼에 종속되지 않는다.

그렇다면 왜 굳이 인터프리팅 작업을 추가하였을까? 당연하게도 이러한 복잡한 구조가 다양한 장점을 제공하기 때문이다.

- JVM은 하드웨어로 구현하기 어려운 기능을 제공한다.

- JVM에서 실행되기 때문에 플랫폼에 종속되지 않는다. 

참고할만한 주소: https://m.blog.naver.com/ehcibear314/221228200531

 

3.5. C

앞서 언급하였듯이 CPU마다 명령어가 다르다 보니, CPU마다 프로그램을 다시 만들어야하는 불편함이 존재하였다. 이를 해결하기 위해 컴파일러와 C 언어가 함께 등장하였다.

소스 코드는 컴파일 과정을 거쳐 기계어 혹은 오브젝트 코드가 된다. CPU마다 기계어와 어셈블리 언어가 다르기 때문에, 당연하게도 컴파일러 또한 CPU마다 다르다.

우리가 흔히 C 혹은 C++언어로 코드를 작성할 때 사용하는 Visual Studio는 윈도우 환경의 컴퓨터에서 X86, X64, ARM 등의 CPU에서 컴파일 되도록 지원한다.

어셈블리어는 CPU에도 영향을 받지만, 운영체제에도 영향을 받는다. 운영체제 마다 커널이 상이하기 때문이다. 즉, 같은 CPU를 사용하더라도 윈도우 프로그램이 리눅스에서 실행될 순 없다. 이는 운영체제에 따라 코드가 동일하여도 실행파일이 다르기 때문이다.

프로그램의 목적 코드는 운영체제의의 포맷에 맞추어 구성되어야 하는데, 이 역할을 링커가 수행한다. 즉, 링커는 목적 파일을 결합하여 해당 운영체제에서 실행 가능한 하나의 파일을 만드는 작업을 한다. 

참고할만한 주소: https://psyhm.tistory.com/1

 

 

'Computer Science > Computer Knowledge' 카테고리의 다른 글

컴퓨터의 구조 - 8  (0) 2021.09.07
컴퓨터의 구조 - 7  (0) 2021.09.06
컴퓨터의 구조 - 5  (0) 2021.09.01
컴퓨터의 구조 - 4  (0) 2021.08.26
컴퓨터의 구조 - 3  (0) 2021.08.25