C, Cpp

C언어를 기계어로 변환해보기

흑조롱이 2023. 9. 14. 07:22

1. C언어가 기계어로 컴파일 하는 과정

 

 

C언어를 실행하기 위해 거치는 과정들[1]

 

요약하자면,

  

     C언어로 파일 작성

-> 컴파일러(Compiler)에서, 어셈블리어로 변환(확장자: .s)  

-> 어셈블러(Assembler)에서, 어셈블리어를 기계어로 변환(확장자: .o)   

-> 링커(Linker)에서, 실행파일(.exe) 생성[2]

 

 

VSCode에서 개발할 때는 어셈블리어로 컴파일 하기 전에, 전처리한 파일을 생성한다.

 

이는 Visual Studio Intermediate File 이라고 하며, 확장자는 .i 이다.

 

그러면, Intermediate File, 어셈블리 파일, object 파일(.o)이 어떻게 생겼는 지 gcc를 이용해서 살펴보자.

 

 

 

 

2. gcc로 .i, .s, .o 파일 만드는 과정

 

 

 

입력받은 정수 2개를 곱한 결과를 출력하는 프로그램이 있다고 하자.

 

// 이름: quest5.c
#include <stdio.h>


int main(void)
{
    int n = 0;
    int k = 0;
    printf("Enter an integer: ");
    scanf("%d", &n);  
    printf("Enter another integer: ");
    scanf("%d", &k);  

    printf("%d \n", n * k);

    return 0;
}

 

그러면 위 코드를 순서대로 컴파일, 어셈블 해보자

 

 

 

1) c -> i

 

 

어셈블리어로 변환하기 전에, 전처리를 한 intermediate file을 만들어주자.

 

이를 위해 아래의 명령어를 수행해주자.

 

gcc -E quest5.c -o quest5.i // -E: 전처리만 하고, 컴파일/어셈블은 수행 안함 -o: 결과를 출력할 파일

 

 

그 결과로 아래처럼 intermediate file이 생성되었다.

 

 

전처리한 모습

 

 

2) i -> s

 

 

위에서 전처리를 거친 파일을 어셈블리어로 변환해보자.

 

gcc -S quest5.i -o quest5.s // -S: 어셈블리어로 컴파일만 수행하기

 

 

그러면 우리가 아는 어셈블리어 형식의 파일을 볼 수 있다.

 

아직은 기계어 수준이 아니므로, 이를 한번 더 변환해야 한다.

 

 

 

 

3) s -> o

 

 

어셈블리어를 기계어로 어셈블 해 볼 차례이다.

 

 

gcc -c quest5.s -o quest5.o // -c: 컴파일 후 어셈블 까지만 수행함. link까지는 수행안함

 

위의 명령어를 실행하면. 기계어로 쓰인 object 파일이 나오게 된다.

 

하지만 object파일을 VSCode로 바로 열어보면, 거의 읽을 수 없는 모습으로 나온다.

 

 

VSCode에서 열어본 object 파일 (quest5.o)

 

 

위의 파일을 010editor, HxD 등 Hex editor 로 열어보면 아래와 같은 모습을 확인할 수 있다.

 

HxD로 열어본 object 파일

 

 

 

3. o 파일의 특징

 

 

window에서 objdump를 한 모습

 

object 형식의 파일은 기계어로 쓰여있기에, 바로 보기에는 곤란한 점이 있다.

 

보는 방법으로는, objdump를 통해 명령창에 어셈블리어의 형식으로 표시하거나, HxD 등 별도의 text editor를 사용하는 등의 방법이 존재한다.

 

 

 

 

 

4. 원도우/리눅스별 나오는 .o 파일 차이 

 

 

리눅스 환경에서 object 파일을 만들 경우, 이는 ELF(Executable & Linkable Format)포맷을 가진다. 

 

하지만 윈도우 환경에서 object파일을 만들 경우, ELF 대신 다른 포맷을 가지는 object파일이 나오게 된다.

 

리눅스 환경에서 나온 object 파일

 

윈도우에서 나온 object 파일

 

리눅스에서 나온 .o 파일, ELF 형식

 

objdump로 읽어온 object 파일

 

 

5. object파일을 실행 파일로 만들기

 

 

마지막으로, 리눅스 환경에서 만든 object파일을 실행 파일로 만들어보자.

 

아래처럼 gcc를 통해 object파일을 실행 파일로 변환할 수 있다.

 

gcc quest5.o -o quest5 // quest5.o: 앞서 만든 object파일 이름

 

 

실행파일을 readelf로 읽어온 모습

 

 

 

object 파일을 objdump 했을 때 보다, 내용이 더 많아졌다.

 

이는 실행에 필요한 함수들 때문에, 내용이 object파일보다 더 길어진 것이다.

 

 

 

 

<참고자료>

[1] https://oliviagallucci.com/converting-high-level-languages-to-machine-language/