본문 바로가기
시스템 반도체/컴퓨터 구조 (RISC-V)

컴퓨터 구조 Cross compilation ( makefile, Preprocessing, compilation, Assembler, Linker )

by 전컴반 2022. 2. 23.
반응형

아래 내용을 유튜브에도 정리해 놨습니다!

 

https://youtu.be/cpvQbqpfeGw

 

High-Level 언어

 

High-Level 언어 (C, JAVA..)는 컴퍼일러를 거쳐 Assembly 언어로 바뀌고 Assembly 언어는 Assembler를 거쳐서 Machine code (binary, object)로 바뀐다. 

이렇게 하여 우린 0110101과 같은 숫자가 아닌 상위 언어를 이용하여 컴퓨터와 소통할 수 있게 됐다.

 

저작권침해의사없음

 

동작 실행 순서에는 아래와 같은 단계를 거쳐 이루어진다

 

1. Preprocessing : 실행할 코드를 가져오는 단계. #include같은 #지시자에 따라 소스코드의 주소를 적절히 변경한다

2. Compilation : Preprocessing 된 코드를 Assmbley 언어로 바꿔주는 단계

3. Assembler : Assmbely 언어를 Machine code로 바뀌 주는 단계

4. Linker : 변형된 Machine code와 library를 하나로 묶어 실행파일을 만드는 단계

 


 

Cross compilation은 어떤 머신 코드 기반에서 동작하냐에 따라서 Linker의 기능이 추가되나 안되냐로 나눠진다.

기본 Native compilation을 사용하면,

 

1. Preprocessing

2. compilation

3. Assembler

 

이렇게 세 단계로 할 수 있지만, Cross compilation을 사용하면

4. Linker가 추가된다.

 

기본 예제를 이용하여 각각 단계별로 어떻게 되는지, 어떤 결과가 나오는지 확인해보자.

 

먼저, 기본 소스 코드를. c로 만든다. 이 코드가 어떻게 컴파일되는지 보려는 것이다.

 

#define min(x,y) ((x) < (y) ? (x) : (y))

int compare(int b, int c)
{
    int a;
    a = min(b, c);
    return a;
}

 

이 파일을 어떻게 컴파일할 것인지 makefile을 만들어 동작한다.

make file이란 컴파일을 어떻게 할 것인지 미리 정해 놓는 파일이다. 여러 명이 협업을 하거나 코드 줄 수가 너무 많을 때, 하나하나 컴파일하는 것 아니라 어떻게 할 것인지 미리 정해놔서 자동화해 놓는다고 생각하면 된다.  즉, 미리 정한 과정에 따라 컴파일이 이루어진다.

 

위에 여러 파일이 있지만 필요한 부분만 보자,

 

Preprocessing

 

$(CPP) compare.c > compare.i // Preprocessing

 

먼저 Preprocessing을 수행하기 위해선 $(CPP)를 불러온다. Preprocessing을 하는 동작 파일을 위에서 주소로 지정해줬다.. cpp파일로 하라는 명령이다.

뒤에 젹혀 있는 말은 compare.c를 이용하여 compare.i를 만들어낸다. 여기에는 source코드를 Preprocessing 한 코드가 적혀있다. 실행하면 compare.i라는 파일이 source 쪽에 생긴다. 열어보면 아래와 같이 생겼다.

 

compare.i

# 1 "compare.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "compare.c"


int compare(int b, int c)
{
 int a;
 a = ((b) < (c) ? (b) : (c));;
 return a;
}

 

Compilation

 

$(CC) -Wall -S compare.i   // Compiling

다음으로 $(CC) 또한 마찬가지로 compling 하는 파일을 주소로 지정해줬다. 위에서 Preprocessing 된 파일을 컴파일하는데 이때. gcc 파일을 이용한다. 

 

어셈블리 언어로 보인다. 봐도 뭘 말하는지는 잘 모르겠다. 아마 이런 동작을 한다는 걸 보여주는 것 같다. 아직 정확한 메모리 상의 주소는 적혀있지 않다. 

 

compare.s

	.file	"compare.c"
	.option nopic
	.attribute arch, "rv32i2p0_m2p0_a2p0_c2p0"
	.....
compare:
	addi	sp,sp,-48
	sw	s0,44(sp)
	addi	s0,sp,48
	.....
.L2:
	sw	a5,-20(s0)
	lw	a5,-20(s0)
	.....

 

Assembly

 

$(AS) $(ASFLAGS) compare.s -o compare.o  // Assembling (compare.s)
$(OBJDUMP) -xS compare.o > compare.dump  // Disassembling the object code

 

바로 이어서 $(AS)는 Assembling을 동작하고 어셈블리 언어로 변환해준다. 어셈블리 언어에서 덤프 파일을 만드는데 덤프 파일이란, 기억 정보를 기록하는 파일이다. 어셈블 언어와 주소를 알려준다. 위에선 동작만 적혀있었다면 여기선 명확한 주소까지 명시하며 알려준다.

 

compare.dump

......
Disassembly of section .text:

00000000 <compare>:
	.text
	.align	1
	.globl	compare
	.type	compare, @function
compare:
	addi	sp,sp,-48
   0:	fd010113          	addi	sp,sp,-48
	sw	s0,44(sp)
   4:	02812623          	sw	s0,44(sp)
	addi	s0,sp,48
	......

00000024 <.L2>:
.L2:
	sw	a5,-20(s0)
  24:	fef42623          	sw	a5,-20(s0)
	lw	a5,-20(s0)
 	.....

 

Linking

 

$(LD) $(LDFLAGS)  lab0.o compare.o -o labcode  // Linking

 

이제 Linking을 수행하면 아래와 같다. 바로 위에 코드와 똑같아 보이지만 위에 다르다.

 

.......
Disassembly of section .text:

00000000 <compare-0x10>:
.text
.align 4

	la sp, stack
   0:	40000113          	li	sp,1024
	j	compare
   4:	00c0006f          	j	10 <compare>
	......

00000010 <compare>:
	.text
	.align	1
	.globl	compare
	.type	compare, @function
compare:
	addi	sp,sp,-48
  10:	fd010113          	addi	sp,sp,-48
	sw	s0,44(sp)
  14:	02812623          	sw	s0,44(sp)
	.......
.L2:
	sw	a5,-20(s0)
  34:	fef42623          	sw	a5,-20(s0)
	lw	a5,-20(s0)
 	.......
반응형

댓글