이 둘은 서로 협력하여 응용 소프트웨어를 실행한다.
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
hello 프로그램은 hello.c라는 파일에 저장된다.
소스 파일은 0 또는 1로 이루어진 비트의 시퀀스이며, 바이트라는 8비트 단위로 구성된다.
대부분의 컴퓨터 시스템은 텍스트 문자를 ASCII표준을 사용하여 표시한다.
hello.c 처럼 오직 ASCII 문자로만 이루어진 파일을 텍스트 파일이라고 부르며,
다른 모든 파일은 바이너리 파일이라고 한다.
hello 프로그램은 인간이 읽고 이해할 수 있으므로 고급 C프로그램으로 일생을 시작한다.
컴퓨터 시스템에서 hello.c를 실행시키려면 각 문장을 다른 프로그램들에 의해
저급 기계어 인스트럭션(machine language instruction)들로 번역되어야 한다.
이 인스트럭션들은 실행가능 목적 프로그램(executable program)이라는 형태로 합쳐져서 바이너리 파일로 저장된다.
compiler는 UNIX 시스템에서 다음과 같이 소스 파일에서 오브젝트 파일로 번역할 수 있다.
linux > gcc -o hello hello.c
GCC 컴파일러 드라이버는 hello.c 소스파일을 읽어서 hello 실행파일로 번역한다.
번역은 4단계를 거치는데 이 4단계를 컴파일 시스템이라고 한다.
flowchart LR
pp["Pre-processor(cpp)"]
comp["Compiler(cc1)"]
assem["Assembler(as)"]
linker["Linker(ld)"]
start[" "] --hello.c--> pp
pp --hello.i--> comp
comp --"hello.s"--> assem
assem --"hello.o"--> linker
linker --"hello"--> endee[" "]
main:
subq $8, %rsp
movl $.LCO, $edi
call puts
movl $0, $eax
addq $8, %rsp
ret
어셈블리어는 여러 상위수준 언어의 컴파일러들을 위한 공통의 출력언어를 제공하기 때문에 유용하다.
프로세서는 메모리에 저장된 인스트럭션을 읽고 해석한다.
linux> ./hello
hello, world
linux>
쉘은 커맨드라인 인터프리터로 프롬프트를 출력하고 명령어 라인을 입력받는다.
명령어 라인이 내장 쉘 명령어가 아니면 쉘은 실행 파일의 이름이라고 판단하고 해당 파일을 실행한다.
hello 프로그램이 실행될 때 전형적인 시스템에서 하드웨어 조직을 이해할 필요가 있다.

프로세서는 PC가 가리키는 인스트럭션을 반복적으로 실행하고, PC가 다음 인스트럭션의 위치를 가리키도록 업데이트 한다.
이러한 단순한 동작들은 메인 메모리, 레지스터파일, 수식/논리 처리기 주위를 순환한다. 레지스터 파일은 각각 고유의 이름을 갖는 워드 크기의 레지스터 집합으로 구성되어 있다.
./hello 를 쉘에 입력하면 쉘 프로그램은 각 문자를 레지스터에 읽어 들인후 메모리에 저장한다.

키보드에서 엔터키를 누르면 쉘은 파일 내의 코드와 데이터를 복사하는 인스트럭션을 실행하고 실행파일 hello를 디스크에서 메인 메모리로 로딩한다.

hello 파일의 코드와 데이터가 메모리에 적재되면, 프로세서는 hello 프로그램의 main 루틴의 인스트럭션을 실행한다.
이 인스트럭션 들은 스트링을 메모리에서 레지스터로 복사하고 레지스터에서 디스플레이로 전송하여 화면에 글자가 표시된다.
