혼자 정리

[CSAPP] 3.2 프로그램의 인코딩(Program Encodings) 본문

CSAPP정리

[CSAPP] 3.2 프로그램의 인코딩(Program Encodings)

tbonelee 2021. 6. 22. 12:13

p1.cp2.c의 C프로그램 작성한다고 가정.

Unix 커맨드 라인에서 컴파일하려면 다음의 명령어 작성.

linux> gcc -Og -o p p1.c p2.c
  • gcc는 GCC C 컴파일러를 지칭.
  • -Og옵션은 원본 코드의 전체 구조를 따르는 정도의 최적화를 하는 수준으로 기계어 코드를 생성한다. 더 높은 수준의 최적화 진행시 기존 C 코드의 전체적 구조를 변형시킬 가능성이 존재. 여기서는 학습을 위해 이 옵션을 사용할 것.

GCC가 소스 코드를 실행 가능한 코드로 변환하는 과정은 다음과 같다.

  1. C _전처리기(preprocesor)_는 소스 코드 내의 #include#define 선언 같은 지시자들의 내용을 소스 코드에 삽입해준다.
  2. _컴파일러_가 각각의 소스 파일들의 어셈블리 코드 버전인 p1.sp2.s를 생성한다.
  3. _어셈블러_가 어셈블리 코드 버전의 바이너리 _오브젝트-코드_파일인 p1.op2.o를 생성한다.(오브젝트 코드는 기계 코드의 형태로 모든 인스트럭션의 바이너리 형태를 담고 있다. 하지만 전역 값들의 주소는 아직 채워지지 않은 상태이다.)
  4. _링커_가 오브젝트-코드 파일들을 코드를 구현한 라이브러리 함수(printf같은)들과 함께 통합해서 실행 코드 파일인 p(-o p 옵션을 통해 주어짐)를 생성한다. 실행 파일은 우리가 살펴볼 두번째 기계 코드로(첫번째 기계 코드는 어셈블리어?) 프로세서가 직접적으로 실행하는 코드의 형태이다.
    이 과정의 더 자세한 것은 7장을 참조..

3.2.1 기계수준 코드(Machine-Level Code)

1.9.3에서 컴퓨터 시스템이 추상화 모델을 통해 세부 구현을 감추면서 시스템을 운영한다고 했는데, 추상화 중 두 가지가 기계수준 프로그래밍에서 특히 중요.

  1. 기계수준 프로그램의 형식과 동작은 _인스트럭션 집합구조(Instruction Set Architecture; ISA)_에 의해 정의된다. ISA는 프로세서 상태, 인스트럭션 형식, 프로세서 상태에 대한 인스트럭션의 영향들을 정의한다. 또한 대부분의 ISA는 인스트럭션들의 순차적으로(하나의 인스트럭션이 다음 인스트럭션 전에) 실행되는 것처럼 프로그램의 동작을 정의한다. 실제로는 여러 인스트럭션들을 동시에 실행하지만 전체 동작은 순차적으로 실행되는 것처럼 보인다.
  2. 기계수준 프로그램은 _가상주소_를 사용하고, 이는 메모리가 하나의 큰 바이트 배열처럼 보이게 해준다. 실제 메모리는 여러 메모리 하드웨어와 OS로 구현되어 있다.
  • 프로그램 카운터(Program Counter;PC)(x86-64에서는 %rip라 부름) : 실행할 다음 인스트럭션의 메모리 주소를 가리킴.
  • 정수값인 _레지스터 파일(register file)_은 16개의 이름이 붙여진 64비트 값을 담고 있다. 각 레지스터들은 C 포인터에 대응되는 주소값이나 정수 데이터를 담고 있을 수 있다. 어떤 레지스터는 프로그램의 중요 부분을 기록하며 따라가는데 사용될 수 있고 다른 부분은 인자, 프로시저의 지역 변수, 함수의 반환값 같은 일시적인 데이터를 담는 데 사용될 수도 있다.
  • 조건코드 레지스터는 가장 최근에 실행된 산술/논리 인스트럭션에 대한 상태 정보를 담고 있다. 이는 ifwhile문을 구현할 때 필요한 제어나 데이터 흐름의 조건에 따른 변화를 구현하기 위해 사용됨.
  • 벡터 레지스터의 집합은 한 개 이상의 부동소수점 값을 담을 수 있다.

C에서는 서로 다른 데이터 타입 선언하고 메모리 할당. But, 기계어 코드는 메모리를 하나의 큰 배열로 처리.
C에서 배열, 구조체는 연속적인 바이트로 표시. 스칼라 데이터 타입에도 부호형, 비부호형, 포인터, 정수형 모두 구분하지 않는다.

프로그램의 메모리는 프로그램 실행 기계어 코드, 운영체제 위한 일부 정보, 프로시저 호출과 리턴 관리하는 런타임 스택, 사용자에 의해 할당된 메모리 블록 등을 포함.


3.2.3 형식에 대한 설명

linux> gcc -Og -S mstore.c

위 명령어 통해 mstore.s를 생성하면 다음과 같은 내용을 볼 수 있다. (어셈블리어로 작성된 파일)

        .file "010-mstore.c"
        .text
        .globl multstore
        .type multstore, @function
multstore:
        pushq   %rbx
        movq    %rdx, %rbx
        call    mult2
        movq    %rax, (%rbx)
        popq    %rbx
        ret
        .size multstore, .-multstore
        .ident "GCC: (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1" .section .note.GNU-stack,"",@progbits

'.'으로 시작하는 줄은 어셈블러와 링커에게 지시하기 위한 줄로 실제 인스트럭션만 보고자할 때는 크게 신경쓰지 않아도 된다.