Skip to content

3.2 Programming Encodings


인코딩이라는것이, 결국 변환이라는 작업을 뜻하는 것이었고, 컴파일러(특히 GCC 컴파일러)가 C 코드를 변환해 돌리려고 하는 아키텍처의 명령어셋의 언어로 쓰여진 이진파일로 만드는 과정을 보여준다.

대부분의 명령어셋 아키텍처(ISA)는 순차적으로 읽히고 실행되게끔 만들어졌지만, 더 높은 성능향상을 위해 기계는 동시에 여러 명령어들을 한 번에 가져와 실행시킨다. 이때 발생할 수 있는 오차를 줄이기 위한 일종의 방어장치도 있아고 한다 근데 그게 지금 단원이랑 어울리는 내용이기는 한가?

자문자답#

  • 전처리에서 무슨 일을 해요?
  • 어셈블러가 목적파일로 코드를 변환했다고 바로 실행할 수 없는 이유가 뭐예요?
  • 라이브러리 함수들 (printf)은 어디에 있고 언제 불러와져요?

INDEX#

  • 3.2.1. Machine Level Code
  • 3.2.2. Code Examples
  • 3.2.3. Notes on Formatting

3.2.1 Machine Level Code#

  • 프로그래머로부터 가려진 중요한 프로그램의 상태들 (registers)
    • PC(Program Counter): 다음 실행할 명령어의 위치를 저장하고 있음. %rip
    • 다양한 방식으로 활용될 수 있는 16개의 64비트 레지스터: 임시 값 저장, 인자, 지역변수, 리턴값
    • 조건문에서 활용할 수 있는 레지스터는 if, for, while문 등에서 계산된 연산결과를 저장하고 있다가 요긴하게 쓰일 수 있다고 한다.
    • x86-64에서는 벡터 데이터를 저장하는 레지스터도 있다고 하대?
  • 어셈블리 단에서는 배열이나 구조체를 그저 바이트 뭉치로 볼 뿐이다. 더군다나 데이터의 타입도 분해되어 signed integer, unsigned integer, 포인터 등등을 전혀 구별하지 않는다. 우리는 무의미한 바이트의 집합으로부터 의미를 해석하는 작업을 하고 있었던 것이다.

p.457 disassembler로 뜯어본 바이너리 코드

  • x86-64 명령어 셋은 그 크기가 1byte ~ 15byte로 다양하다. 단순하고 인자가 적은 명령어도 굳이 1워드를 가득 채울 필요가 없기 때문이다.
  • 명령어 형식은 시작위치가 정해진 경우가 있다. 예를 들어 pushq rbx 명령은 바이트값 53으로 시작할 수 있다.
  • disassembler는 GCC의 이름규칙과 다르다는 점 참고.