~소스 코드와 명령어~
저급언어의 두가지
- 기계어
- 어셈블리어
기계어는 0과 1로 이루어진 명령어로 구성된 저급 언어이다. 16진수로 표기되기도 한다.
기계어를 사람들이 읽고 쓰기 편한 형태로 변환한 저급언어가 어셈블리어
정리하면…
어셈블리어는 0과 1로 이루어진 기계어를 읽기 편한 형태로 번연한 저급 언어이다.
고급언어가 저급언어로 변환되는 과정에는 크게 2가지 방식이 존재
- 컴파일
- 인터프리트
컴파일 언어가 저급언어로 변환되는 과정:
고급언어(소스코드) -> 컴파일(컴파일러) -> 저급언어(목적코드/object code)
정리하자면 컴파일 언어로 작성된 소스코드는 컴파일러에 의해 저급 언어로 변환이 되고(이 과정을 컴파일이라고 한다). 컴파일 결과로 저급 언어인 목적 코드가 생성이 된다.
(더욱 자세한 단계가 존재+추가강의존재)
인터프리트언어
- 인터프리터에 의해 한줄씩 실행
- 소스 코드 전체가 저급 언어로 변환되기까지 기다릴 필요가 없음.
일반적으로 컴파일 언어는 처음부터 끝까지 전부 훑고 오류 없는지 사용되지 않는 변수 이런걸 다 보고 통째로 컴파일.
컴파일 언어의 경우 코드에 에러가 존재할 경우에 컴파일 전에 사용자에게 컴파일을 할수가 없다고 전달.
반면에 인터프리터는 오류 직전의 코드를 정상적으로 실행을 시킴.
cpu의 종류마다 컴파일되는 코드가 다를 수 있다.
세상의 모든 언어가 인터프리트언어와 컴파일언어로 양분되지는 않는다. 둘의 경계가 애매한 경우들이 있다. 두가지 방식은 고급언어가 저급언어로 변환되는 대표적인 방식중 하나이다로 이해바람.
~~~명령어 구조~~~
저급 언어는 명령어들로 이루어져 있다는데 그럼 명령어 하나하나는 어떻게 생겼을까?
명령어는 연산코드와 오퍼랜드로 구성되어 있다.
예) Add eax edx
오퍼랜드는 연산에 사용될 데이터 or 연산에 사용될 데이터가 저장된 위치(이게 더 자주 저장됨)
오퍼랜드가 담기는 공간 즉 오퍼필드를 주소필드라고 부르기도 한다.
오퍼랜드가 없는경우도 한개일 수도 있고 여러개일 수도 있음.
연산 코드
수행할 연산. cpu마다 다른 연산 코드를 가지고 있음. 공통적인 종류는 다음 4가지
- 데이터 전송
- 산술/논리 연산
- 제어흐름 변경
- 입출력 제어
데이터 전송 연산 코드:
- MOVE: 데이터를 옮겨라, 예를 들어 어떤 레지스터에서 어떤 레지스터로 옮겨라
- STORE: 메모리에 저장하라
- LOAD(FETCH): 메모리에서 CPU로 데이터를 가져와라
- PUSH: 스택에 데이터를 저장하라
- POP:스택의 최상단 데이터를 가져와라
산술 논리연산:
- ADD/ SUBTRACT/ MULTIPLY / DIVIDE
- INCREMENT / DECREMENT: 오퍼랜드에 1을 더라하 / 빼라
- AND / OR / NOT: AND / OR / NOT연산 수행
- COMPARE : 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라
제어 흐름 변경, 특정 메모리 주소로 실행의 순서를 점프해서 옮기는 유형의 연산 코드
- JUMP : 특정 주소로 실행 순서를 옮겨라
- CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
- HALT : 프로그램의 실행을 멈춰라
- CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
- RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라
입출력 제어
- READ(INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
- WRITE(OUTPUT) : 특정 입출력 장치로 데이터를 써라
- START IO : 입출력 장치를 시작하라
- TEST IO : 입출력 장치의 상태를 확인하라
여기서 질문, 왜 오퍼랜드에는 연산에 사용될 데이터의 주소값이 저장?
답: 왜냐하면 메모리가 부족해서, 주어진 데이터의 크기가 한정적. 오퍼랜드가 많을 수록 차지할 수 있는 공간 더 줄어듬.
유효주소(effective address)
- 연산에 사용할 데이터가 저장된 위치, 즉 오퍼랜드에 적혀있는 값.
명령어 주소 지정 방식(addressing modes)
- 연산에 사용할 데이터가 저장된 위치를 찾는 방법
- 유효 주소를 찾는 방법
- 다양한 명령어 주소 지정 방식
즉시 주소 지정 방식(immediate addressing mode)
- 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시
- 가장 간단한 형태의 주소 지정 방식
- 연산에 사용할 데이터의 크기가 작아질 수 있지만, 빠름
직접 주소 지정 방식(direct addressing mode)
- 오퍼랜드 필드에 유효 주소 직접적으로 명시
- 유효 주소를 표현할 수 있는 크기가 연산 코드만큼 줄어듦
간접 주소 지정 방식(indirect addressing mode)
- 오퍼랜드 필드에 유효 주소를 명시
- 앞선 주소 지정 방식들에 비해 속도가 느림
- 유효주소의 주소 -> 유효 주소 -> 연산에 사용할 데이터
레지스터 주소 지정 방식(register addressing mode)
- 연산에 사용할 데이터가 저장된 레지스터 명시
- 메모리에 접근하는 속도보다 레지스터에 접근하는 것이 빠름
레지스터 간접 주소 지정 방식(register indirect addressing mode)
- 오퍼랜드에 유효 주소를 저장한 레지스터가 존재, 그리고 레지스터에 유효 주소가 있고 메모리에 연산에 사용할 데이터가 있는 방식
- 연산에 사용할 데이터를 메모리에 저장
- 그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시
~~~C언어의 컴파일 과정~~~
C언어의 컴파일 과정:
test.c->전처리기 -> 컴파일러 -> 어셈블리 -> 링커->test.exe
test.c->전처리->test.i
전처리 과정:
- 본격적으로 컴파일 하기 전에 처리할 과정
- 외부에 선언된 다양한 소스 코드, 라이브러리 포함
- 프로그래밍의 편의를 위해 작성된 매크로 변환
- 컴파일할 영역 명시
Test.i->컴파일->test.s
컴파일 과정
- 전처리가 완료되어도 여전히 소스 코드
- 전처리 완료된 소스 코드를 저급 언어(어셈블리어)로 변환
test.s->어셈블->test.o
어셈블 과정
- 어셈블리어를 기계어로 변환
- 목적코드를 포함하는 목적 파일이 됨
목적파일 vs 실행파일
- 목적파일과 실행파일은 둘다 기계어로 이루어진 파일
- 목적파일은 링킹을 거친 이후에야 실행 파일이 된다.
- 링킹은 과정은 다른 파일의 함수를 끌어다 쓸때 main파일과 연결시켜주는 역할을 한다.
'What I Learned' 카테고리의 다른 글
[WIL] Day 17 (0) | 2023.06.19 |
---|---|
[WIL] Day 16 (0) | 2023.06.18 |
[WIL] Day 14 (0) | 2023.06.10 |
[WIL] Day 13 (0) | 2023.06.09 |
[WIL] Day12 (기말준비 Day3) (0) | 2023.06.09 |
댓글