프로그램의 실행과정과 원리 - 컴파일, 하드웨어

첫번째 정글 TIL - CSAPP Ch.1

Hello World!

소스 프로그램(소스 파일)

#include <stdio.h>

int main()
{
    printf("Hello World");
    return 0;
}

hello.c

소스 프로그램으로 생성, hello.c라는 텍스트 파일로 저장

0 또는 1로 표시되는 비트들의 연속, Byte로 구성됨

텍스트 문자 ASCII 표준 사용하여 표시

ASCII - 각 문자를 바이트 길이의 정수 값으로 표현

텍스트 파일과 바이너리 파일

  • 텍스트 파일 - 아스키 문자로만 이루어짐(ex. hello.c)

    ASCII나 Unicode 등의 문자 인코딩을 사용하여 사람이 읽을 수 있는 문자 형태로 데이터를 저장

  • 바이너리 - 다른 모든 코드

    0과 1로 이루어진 이진 형식으로 데이터를 저장

모든 시스템 내부의 정보는 비트로 표시


컴파일 compile

소스 프로그램은 실행되기 위해 각 C 언어 문장들이 다른 프로그램에 의해 저급 기계어 명렁어(low-level machine-language instruction, 저급 수준의 명령어)들로 번역되야함

언어의 추상화에 따른 분류

  • High-level language(고급언어) 사람이 이해하기 쉬운 문법과 추상화를 제공하는 언어 → 저급언어를 제외한 모든 것

  • Low-level language(저급언어)

    기계어와 어셈블리어를 포함하는 용어

    컴퓨터 하드웨어 가까운 수준에서 동작하는 프로그래밍 언어

  • Machine language(기계어)

    컴퓨터 하드웨어가 직접 이해하고 실행할 수 있는 저급 수준의 프로그래밍 언어

Middel-level language(중급언어)란 있나?

전통적 정의로는 중급어는 없음.

C언어는 고급언어에 속함. 스크립팅 언어가 매우 높은 언어를 사용하고 있기 때문에, 상대적인 위치 비교를 위해 생긴 말 [2][3][4][5]

명령어들은 실행가능 목적 프로그램(xecutable object program) 형태로 합쳐저 바이너리 디스크 파일로 저장

컴파일러 드라이버는 소스파일에서 오브젝트 파일로 번역

→ GCC 컴파일러 드라이버는 소스파일을 열어 실행파일인 hello로 번역

번역은 4단계를 거침

컴파일 시스템

전처리기, 컴파일러, 어셈블리, 링커 → 컴파일 시스템

번역의 4단계

  1. 전처리(Pre-processor) : C 프로그램을 #문자로 시작하는 directive에 따라 수정

    #include<stdio.h> → 시스템 헤더파일인 stdio.h를 프로그램 문장에 직접 삽입하라

    결과로 .i 로 끝나는 새로운 C 프로그램 생성

  2. 컴파일(Compile) : 텍스트 파일 hello.ihello.s 로 번역, 어셈블리어 프로그램 저장

  3. 어셈블리(Assembly) : hello.s 를 기계어 명령어로 번역, 재배치 가능 목적프로그램(relocatable object program) 형태로 묶어 hello.o 라는 목적파일에 그 결과를 저장

  4. 링크(Link) : hello 프로그램이 printf 함수를 호출, printf 함수는 이미 컴파일된 별도의 목적파일 printf.o 에 들어있음. hello.oprintf.o 를 결합하는 통합작업 수행

    결과로 hello 파일이 실행파일로 메모리에 적재되어 실행

Compile vs Build

Compile: 4단계중 컴파일 단계만을 의미

Build: 고급 언어를 저급 언어로 변환하는 전 과정

실행파일을 유닉스 시스템에서 실행하기 위해 쉘(Shell)에 이름 입력

셸(Shell)

커맨드라인 인터프리터로 프롬프트를 출력하고 명령어 라인을 입력 받아 그 명령을 실행

명령어 라인이 내장 쉘 명령어가 아니면 실행파일의 이름으로 판단 → 로딩하여 실행

linux> ./hello 
hello, world 
linux>

시스템 하드웨어 조직

시스템 하드웨어 구성

  • CPU: central processing unit

    ALU: airthemetic/logic unit

    PC: program counter

  • USB: Universal Serial Bus

Buses

시스템 내를 관통하는 전기적 배선군

컴포넌트들 간에 바이트 정보들을 전송

워드(word)로 데이터 전송

워드(word)

고정 크기의 바이트 단위

컴퓨터가 한 번에 처리할 수 있는 데이터의 기본단위

시스템에 따라 워드의 크기가 다름

32비트(4바이트), 64비트(8바이트)

한개의 워드를 구성하는 바이트 수 → 시스템마다 보유하는 기본 시스템 변수

64비트 시스템이 32비트 시스템보다 더 많은 데이터를 한번에 처리할 수 있음

컴퓨터의 성능과 메모리 처리 능력에 직접적인 영향을 미침

I/O Devices(입출력 장치)

input/output device

시스템과 외부세계와의 연결 담당

  • input: 외부에서 컴퓨터로 입력하는 장치

    키보드, 마우스, 스캐너, 마이크

  • output: 모니터, 프린터, 스피커

    컴퓨터에서 처리한 결과를 외부로 출력하는 장치

입출력 장치는 입출력 버스와 컨트롤러나 어댑터를 통해 연결

입출력 버스와 입출력 장치들 간에 정보를 주고받도록 하는 일

컨트롤러와 어댑터의 차이

컨트롤러: 다바이스 자체가 칩셋, 메인보드(마더보드)에 장착됨

특정 유형의 장치를 위해 설계

어댑터: 메인보드 슬롯에 장착됨

다양한 유형의 장치를 지원할 수 있도록 더 유연하게 설계됨(추가 교체가 쉬움)

Main Memory

프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치

물리적 - DRAM(Dynamic Random Access Memory 칩들로 구성

논리적 - 연속적인 바이트들의 배열, 0부터 시작해서 고유의 주소(배열의 인덱스)를 가짐

한개의 프로그램을 구성하는 각 기계어 명령어들은 다양한 바이트 크기를 가짐

Processor(CPU)

CPU(The central processing unit) = Processor

메인 메모리에 저장된 명령어들을 해독(interpret / decode) 및 실행(excute)

프로세서 중심에 워드 크기의 저장장치(또는 레지스터)인 PC(Program counter)가 있다.

PC(Program counter)

다음에 실행할 명령어의 메모리 주소를 저장하는 레지스터

PC는 항상 메인 메모리의 기계어 명령어를 가르킨다.

CPU가 동작하는동안 프로세서는 PC가 가리키는 곳의 명령어를 반복적으로 실행하고 PC값이 다음 명령어를 가르키도록 업데이트함

자동증가 : 명령어가 실행된 후 자동으로 증가하여 다음 명령어를 가리킴

분기와 점프 처리 : 조건문이나 함수 호출등으로 인해 프로그램 흐름 변경시 PC값이 변경됨

명령어(Instruction) 실행 단계(기본적인 CPU 동작 사이클)

  1. 프로세서가 PC가 가르키는 메모리에서 명령어를 읽어오기

  2. 명령어에서 비트들을 해석

  3. 명령어가 지정하는 간단한 동작(연산)을 실행

  4. PC를 다음 명령어 위치로 업데이트

CPU가 수행하는 기본적인 연산들은, 주로 메인 메모리, 레지스터(registers), ALU(airthmetic/logic unit, 수식/논리 처리기)를 중심으로 이뤄진다.

레지스터 - CPU 내부의 고속 저장 장치, 각각 이름이 있는 여러 개의 레지스터로 구성(PC 포함)

ALU : 실제 계산 수행(새 데이터와 주소 값을 계산)

CPU가 수행하는 기본적인 연산 4가지

  1. 로드(Load) : 메모리의 데이터를 레지스터로 가져오는 것

    메인 메모리에서 레지스터에 한 바이트 or 워드를 이전값에서 덮어써서 복사

  2. 저장(Store) : 레지스터의 데이터를 메모리에 저장하는 것

    레지스터에서 레지스터에 한 바이트 or 워드를 이전값에서 덮어써서 복사

  3. 작업(Operate) : 레지스터의 데이터를 ALU를 사용해 계산하는 것

    두 레지스터 값을 ALU로 복사하고 두 개의 워드로 수식 연산 수행, 결과를 덮어쓰는 방식으로 레지스터에 저장

  4. 점프(Jump) : 프로그램의 다른 부분으로 실행 흐름을 옮기는 것

    명령어 자체에서 워드를 추출해 그 워드를 PC에 복사해 이전값을 덮어씀

기본 연산의 조합으로 복잡한 프로그램들이 실행 → CPU가 컴퓨터 프로그램을 실행하는 기본 매커니즘


hello 프로그램 실행 과정 총 정리

  1. 초기상태: 쉘 프로그램이 명령어를 실행하며 사용자가 명령을 입력하기를 기다림

  1. 사용자 입력: 사용자가 ./hello 를 입력하면, 셸이 입력을 한 문자씩 읽어 메모리에 저장

  1. 프로그램 로딩: 사용자가 엔터키를 누르면, 셸이 hello 프로그램 실행을 위해 디스크에서 메인 메모리로 프로그램 코드와 데이터를 로드 이 과정에서 DMA(Direct Memory Access) 기술이 사용되어, CPU를 거치지 않고 디스크에서 메모리로 직접 전송

  1. 프로그램 실행: hello 프로그램의 코드와 데이터가 메모리에 로드되면, CPU는 프로그램의 main 함수에 있는 기계어 명령어를 실행하기 시작

  2. 출력: 프로그램은 hello, world 문자열을 메모리에서 레지스터로, 다시 디스플레이 장치로 전송해 화면에 출력


Reference

컴파일 compile

http://www.btechsmartclass.com/c_programming/C-Computer-Languages.html

Middel-level language(중급언어)란 있나?

https://stackoverflow.com/questions/2904577/is-c-a-middle-level-language

https://www.quora.com/Why-is-C-considered-a-high-level-language-when-it-is-clearly-a-mid-middle-level-language

https://www.cs.mtsu.edu/~xyang/2170/computerLanguages.html

http://www.btechsmartclass.com/c_programming/C-Computer-Languages.html

그 외 이미지

Bryant, R. E., & O’Hallaron, D. R. (2016). Chapter 1. In Computer systems: A programmer’s perspective (3rd ed.). Pearson.

Last updated