CSAPP 1장 "컴퓨터 시스템으로의 여행" 부분을 정리해보았다. 1장이라 뒤에서 나올 컴파일, 기계어표현, 정수 표시 등 뒤에서 배울 내용의 인트로라는 느낌이 강하게 들었다.
// hello.c
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
위의 hello.c
파일은 오로지 아스키 문자들로만 이루어져 있는데, 이러한 파일들은 text files
라고 하며 이외의 파일들은 binary files
로 분류된다.
디스크의 파일들, 메모리에 있는 프로그램 혹은 유저 관련 코드, 네트워크로 주고 받는 데이터들은 bunch of bits
들이다. 011010101010 과 같은 숫자들이라는 것 인데, 해당 숫자가 같더라도 이것을 어떠한 context
에서 읽을 것인지에 따라 의미가 달라진다. 특정 숫자들이 있는데 이를 integer, floating-point number, characer string 혹은 machine instruction 이냐에 따라 다르게 인식할 것 이다.
위의 텍스트 파일을 실행하기 위해서는 우리가 출력하고자 하는 헬로 월드 파일은 저수준의 기계어 명령어들로 translate 되어야하는데,
이러한 저수준의 machine-language instruction 들은 executable object program
의 형태로 합쳐져서 바이너리 형태로 저장된다.
컴파일러가 위의 과정을 수행해서 source
파일을 object
파일로 변환해주는데, 그 과정을 보면 아래 그림과 같다.
연두색의 네 단계를 통해서 hello.c 파일이 바이너리 파일로 변환된다.
Pre-processor (전처리단계) : 전처리기(cpp)라는 것이 # 문자로 시작하는 부분에 해당하는 코드들을 handling한다. 예를 들어 hello.c에는 첫 줄에 <stdio.h>를 include 하게 되어있는데, 전처리기가 stdio.h 파일을 해당 부분에 삽입하게 된다.
Complier(컴파일 단계) : 컴파일러(cc1) 가 전처리 단계에서 .i로 변환 된 텍스트파일을 .s로 변환하는데 이 파일에서는 어셈블리어 언어의 프로그램이 포함되게 된다. 다음과 같은 것이 포함된다는데 아직은 무슨 의미인지 모르겠다.
main:
subq $8, %rsp
movl $.LCO, %edi
call puts
movl $0, %eax
addq $8, %rsp
ret
Assembler(어셈블리 단계): 이 단계에서 기계어로 번역이 되고 relocatable object program
형태로 묶어서 hello.o
라는 파일에 결과를 저장한다. 이 파일은 main함수의 인스트럭션들을 인코딩하기 위한 17바이트를 포함하는 바이너리 파일이다. hello.o
파일부터는 사람이 알아볼 수 없는 데이터의 형상을 하고 있다.
Linker (링크단계):
위 실행되는 hello.c 파일에는 printf
함수가 호출되는데 해당 함수는 이미 컴파일된 별도의 object 파일인 printf.o
에 들어있다. 본 파일은 hello.o
파일과 결합되어야하는데 링커프로그램(ld)가 통합작업을 수행해준다.
그결과인 hello 파일은 executable object file
로서 바이너리 형태로 메모리에 로드된다.
text 파일이 binary 파일로 컴파일 되는 과정을 살펴보았으니, 보다 더 큰 그림을 살펴보자.
cpu는 실행해야할 instruction들을 수행해오면서 hello가 입력받길 기다리고 있을 것 이다. 유저가 "hello"를 입력하면 각 문자를 레지스터에 읽어 들인 뒤, 메모리에 저장한다.
엔터를 누르게 되면 쉘은 실행파일 hello를 디스크에서 메인메모리로 load한다. 이 과정에서는 컴파일이 언제 일어나고, disk에 저장되어 있는 형태는 텍스트파일인지, 바이너리인지 잘 모르겠다.
이때 메모리로 load되는 과정은 DMA 로 디스크에서 메인메모리로 바로 이동된다.
hello object file이 메모리에 load가 되면 cpu는 hello 프로그램의 main 루틴의 기계어 instruction을 실행하게 되고, 이 instruction들은 "hello, world\n" 라는 스트링을 메모리에서 레지스터파일로 복사했다가 디스플레이 장치로 전송한다.
추가적으로,
cpu 관련 얘기를 조금 더 해보자.
cpu core에는 word-size 의 Program Counter(PC) 라는storage device(register)가 있는데 이 PC는 항상 cpu가 수행할 machine level의 instruction이 위치하고 있는 메모리의 주소를 가리키고 있다. cpu는 이 instruction을 읽어와서 인스트럭션의 bit들을 interpret(해석) 하고 수행한 다음, 그 다음 instruction이 있는 위치로 pc를 update한다. 이러한 과정은 메인메모리 - 레지스터 - ALU 에서 실행된다.
CPU에서 실행하는 operation에는 Load, Store, Operate, Jump가 있다.