questionet

CS 기초, 컴파일, 인터프리터, 명령어, 연산코드, 오퍼랜드, addressing mode 본문

Learning questions/기초 개념

CS 기초, 컴파일, 인터프리터, 명령어, 연산코드, 오퍼랜드, addressing mode

orthanc 2024. 4. 9. 10:26

3장


고급언어 (python) -> 저급언어 (기계어 : 2진수 또는 16진수로 표현 / 어셈블리어: 기계어를 좀 더 읽기 편하게 번역한 언어)

예를 들어,
기계어 -> 어셈블리어
01010101   push rbp
11000011   ret

어셈블리어에서는 한줄한줄이 명령어 instruction 가 된다. (시스템 버스를 돌아다니는 명령어들)

고급언어를 저급언어로 변환하는 방법

1. 컴파일
2. 인터프리트

예를 들어, C는 컴파일 해줘야 하는 고급언어다. 그래서 컴파일 언어라고도 한다.
파이썬은 인터프리트 방식으로 작동하는 고급언어다. 그래서 인터프리트 언어라고도 한다.

인터프리트 언어에서는 인터프리터가 소스코드를 한줄씩 저급언어로 변환해 실행한다

컴퍼일 언어에서는 컴파일러가 필요하다
소스코드를 처음부터 끝까지 한번에 저급언어로 변환한다.

컴파일 언어와 인터프리트 언어의 차이:
사람이 작성한 소스코드를 한줄한줄 저급언어로 컴퓨터에게 알려주느냐, 한번에 다 바꿔 알려주느냐의 차이 

파이썬 인터프리터의 작동 방식
소스 코드 읽기: 
인터프리터는 .py 확장자를 가진 파이썬 소스 파일을 읽거나, 대화형 쉘(Interactive Shell)에서 직접 입력된 코드를 받아들입니다.
줄 단위 실행: 
인터프리터는 소스 코드를 한 줄씩 읽어서 해석합니다. 대화형 쉘에서는 사용자가 한 줄을 입력할 때마다 즉시 그 줄을 실행합니다.
바이트코드 변환: 
파이썬 인터프리터는 소스 코드를 바이트코드(bytecode)라는 중간 형태로 변환합니다. 이 바이트코드는 파이썬 가상 머신(Python Virtual Machine, PVM) 위에서 실행됩니다.
실행: 
바이트코드는 파이썬 가상 머신에 의해 실행되며, 이 과정에서 컴퓨터의 CPU가 이해할 수 있는 기계어로 변환됩니다. 이 변환 과정은 사용자가 볼 수 없이 내부적으로 이루어집니다.

파이썬 인터프리터의 종류
CPython: 가장 널리 사용되는 파이썬 인터프리터로, 파이썬의 기본 및 공식 구현입니다. C 언어로 작성되어 있습니다.
IPython: 대화형 파이썬 인터프리터로, 표준 파이썬 쉘보다 향상된 기능을 제공합니다. 데이터 분석과 과학 계산에 유용합니다.
PyPy: JIT(Just-In-Time) 컴파일을 지원하는 파이썬 인터프리터로, CPython보다 빠른 실행 속도를 제공합니다.
Jython: 자바 플랫폼 위에서 실행되며, 자바 클래스와의 통합을 지원합니다.
IronPython: .NET 프레임워크 위에서 실행되며, .NET 라이브러리와의 통합을 지원합니다.


저급언어로 변환된 코드를 목적코드 object 코드 라고도 한다.


목적파일 : 목적코드로 이루어진 파일
목적 파일은 실행파일이 되어야 한다.
목적파일을 실행파일로 만드는 과정에서 실행코드가 필요해진다.
이 실행코드를 만드는 작업을 linking 이라고 한다.

목적 파일(Object File)과 실행 파일(Executable File)은 프로그램 개발 과정에서 생성되는 파일 타입입니다. 이들은 서로 다른 단계에서 사용되며, 다른 목적을 가집니다.

### 목적 파일(Object File)

- **정의**: 
소스 코드 파일(.c, .cpp, .java 등)이 컴파일러에 의해 컴파일된 후 생성되는 중간 파일입니다. 
이 파일은 기계어 코드를 포함하지만, 실행 가능한 프로그램으로는 아직 완성되지 않았습니다. 
목적 파일은 종종 라이브러리 호출이나 다른 외부 참조에 대한 '미해결 참조'(unresolved references)를 포함합니다.
- **파일 확장자**: `.o` (UNIX/Linux), `.obj` (Windows)
- **예시**: 만약 `hello.c`라는 C 소스 코드 파일이 있다면, 이를 컴파일하면 `hello.o` (UNIX/Linux) 또는 `hello.obj` (Windows)라는 목적 파일이 생성됩니다.

### 실행 파일(Executable File)

- **정의**: 
목적 파일들이 링커(Linker)에 의해 하나로 결합되고, 모든 미해결 참조가 해결된 최종적인 파일입니다. 
실행 파일은 운영 체제에 의해 직접 실행될 수 있는 파일로, 사용자가 프로그램을 실행하기 위해 사용합니다.
- **파일 확장자**: `.exe` (Windows), 없음 또는 `.out` (UNIX/Linux), `.app` (macOS)
- **예시**: 위의 `hello.o` 또는 `hello.obj` 목적 파일과 다른 필요한 목적 파일들이 링커를 통해 결합되어, 
`hello.exe` (Windows), `hello.out` 또는 단순히 `hello` (UNIX/Linux)라는 실행 파일이 생성됩니다.

### 프로세스 개요

1. **컴파일 단계**: 소스 코드 파일이 컴파일러에 의해 컴파일되어 목적 파일을 생성합니다.
   - 예: `gcc -c hello.c` → `hello.o`
2. **링킹 단계**: 하나 이상의 목적 파일이 링커에 의해 결합되어 실행 파일을 생성합니다.
   - 예: `gcc hello.o -o hello` → `hello` (실행 파일)

이 과정을 통해 개발자는 소스 코드로부터 최종적인 실행 가능한 프로그램을 생성할 수 있습니다.

GCC (GNU Compiler Collection)는 소스 코드를 기계어로 변환하는 컴파일러 모음입니다. 
GNU 프로젝트의 일부로, 주로 C, C++, Objective-C, Fortran, Ada, Go, D 등 여러 프로그래밍 언어를 위한 표준 컴파일러로 사용됩니다.



기계어, 어셈블리어의 명령어는

연산자 피연산자  형식으로 돼 있다. 연산자는 연산코드라고도 한다.
##### @@@@@@@
push  rbp
mov   rbp rsp



피연산자는 연산에 쓸 데이터 또는 그 데이터가 저장된 위치다
예를 들어, 문자, 숫자, 메모리주소, 레지스터 주소. 주로 주소가 온다

##### 0-주소 명령어  : 오퍼랜드(피연산자)가 없는 명령어 

##### @@@@@@@ 1 - 주소 명령어 : 오퍼랜드가 1개 있는 명령어

##### @@@@@@@ @@@@@@@  2- 주소 명령어

##### @@@@@@@ @@@@@@@ @@@@@@@ 3- 주소 명령어




연산자(연산코드) 종류

1. 데이터 전송
MOVE : 데이터를 옮겨라
STORE : 레지스터에 있는 데이터를 메모리에 저장하라
LOAD : 메모리에서 레지스터로 데이터를 가져와라
PUSH : 스택에 데이터를 저장하라
POP : 스택에서 데이터를 가져와라

2. 산술/논리 연산
ADD, SUBTRACT, MULTIPLY, DIVIDE
INCREMENT / DECREMENT
AND, OR, NOT, COMPARE

3. 제어흐름 변경
JUMP : 특정 주소로 실행순서를 옮겨라
conditonal jump
HALT : 중지
CALL : 되돌아올 주소를 저장하고 특정 주소로 실행순서를 옮겨라
RETURN : CALL 했을 때 저장한 주소로 돌아가라

4. 입출력 제어
READ(INPUT) : 특정 입출력 장치에서 데이터를 읽어라
WRITE(OUTPUT)
START IO : 입출력 장치 시작
TEST IO : 입출력장치 상태 확인

##### 를 연산코드 필드
@@@@@@@ 를 오퍼랜드필드, 주소필드 라고 부른다



명령어 크기가 16비트이고 
연산코드 필드가 4비트이고
2-주소 명령어라면 
오퍼랜드로 표현할 수 있는 정보의 개수는 오퍼랜드 하나당 2^6개가 된다.

오퍼랜드에 메모리의 주소를 주면
오퍼랜드 필드 크기보다 메모리가 훨씬 더 크므로
오퍼랜드에 데이터를 직접 줄때보다
더 큰 데이터를 연산할 수 있게 된다


이렇게 오퍼랜드 필드에 데이터가 저장된 위치를 명시할 때
사용할 데이터 위치를 찾는 방법을 addressing mode 라고 한다.

대표적으로 5가지 mode가 있다.

1. immediate addressing mode 
연산에 사용할 데이터를 직접 주는것. 가장 빠름

2. direct addressing mode
데이터가 저장된 위치(유효주소라고 한다. 메모리 주소)를 직접 명시

3. indirect addressing mode
유효주소의 주소를 명시 

4. register addressing mode
레지스터 주소를 유효주소로 직접 명시

5. register indirect addressing mode
연산에 사용할 데이터를 메모리에 저장하고, 그 주소(유효주소)를 저장한 레지스터를 오퍼랜드 필드에 명시

Indirect Addressing Mode 와 Register Indirect Addressing Mode의 차이
Indirect Addressing Mode
이 모드에서는 메모리 주소가 명령어의 피연산자로 사용됩니다. 
즉, 명령어는 메모리 내의 특정 위치를 가리키며, 
이 위치에 저장된 값은 다시 메모리 내의 다른 위치(실제 데이터가 저장된)의 주소를 나타냅니다. 
이렇게 하여, 명령어는 간접적으로 데이터를 참조합니다.
예를 들어, 어떤 메모리 주소에 저장된 값을 다른 위치의 메모리 주소로 사용하여 
실제 데이터에 접근할 수 있습니다.

Register Indirect Addressing Mode
반면, Register Indirect Addressing Mode에서는 명령어의 피연산자로 레지스터 주소만 사용됩니다. 
해당 레지스터는 메모리 주소를 저장하고 있으며, 
CPU는 레지스터에 저장된 메모리 주소를 사용하여 데이터에 접근합니다. 
이 모드에서는 메모리 주소를 직접 피연산자로 사용할 수 없습니다.
이 방식은 데이터에 접근하기 위해 레지스터를 통한 간접 참조를 사용합니다. 
레지스터는 메모리보다 훨씬 빠르게 접근할 수 있으므로, 이 방식은 메모리 접근 속도를 개선할 수 있습니다.

즉, Indirect Addressing Mode는 메모리 주소를 피연산자로 사용할 수 있지만, 
Register Indirect Addressing Mode에서는 레지스터 주소만 피연산자로 사용할 수 있으며, 
이 레지스터가 가리키는 메모리 주소를 통해 실제 데이터에 접근합니다.

Comments