////
Search
Duplicate

Chapter 10. 어셈블리어에서 프로그램의 참모습을 발견하자!

01. 어셈블리어는 네이티브 코드와 1:1로 대응된다!

CPU가 해석하고 실행할 수 있는 것은 네이티브 코드(기계어)로 구성된 프로그램밖에 없다. C언어 등으로 작성된 소스 코드는 각 프로그래밍 언어용 컴파일러로 컴파일되어 네이티브 코드로 변환할 수 있다.
네이티브보다 약간 고급진 어셈블리어(또는 니모닉)가 존재하는데, 각각의 네이티브 코드에 별명을 붙인 것이다.
이 어셈블리어도 끝에 가서는 네이티브 코드로 변환되어야 하며 이를 수행하는 프로그램을 어셈블러라고 한다.

02. 컴파일러로 어셈블리어 소스 코드 만들기

네이티브 코드를 역어셈블하는 방법 외에도 C언어를 어셈블리어의 소스 코드로도 변경할 수 있다.

03. 네이티브 코드로 변환되지 않는 의사 명령어

어셈블리어로 이루어진 소스 코드는 네이티브 코드로 변환되는 일반 명령어와 어셈블러 자체에 대한 명령어인 의사 명령어로 구성되어 있다.
의사 명령어는 프로그램의 구조나 어셈블의 방법을 어셈블러에게 지시하는 명령어로 어셈블 과정을 거쳐도 네이티브 코드로 변환되지 않는다.
의사 명령어로 둘러싸인 부분은 프로그램을 구성하는 명령어나 데이터를 함께 묶은 그룹에 이름을 붙인 것으로 세그먼트라고 부른다.

04. 어셈블리어의 형식 = OP 코드 + 오퍼랜드

어셈블리어에서는 CPU에 대한 하나의 명령어를 한 줄로 나타낸다. 어셈블리어의 명령어 형식은 OP code + operand다. operand로만 구성된 명령어도 있다.
OP code는 명령어가 가진 기능을 나타내며 operand는 명령어의 대상이 되는 것을 말한다. 일종의 동사, 목적어로 해당한다.
operand가 둘 이상인 경우 ,를 사용하여 구분한다.
사용 가능한 OP code의 종류는 CPU의 종류에 따라 달라지며 앞서 설명한 것처럼 네이티브 코드는 메모리에 적재된 후 실행되는데 메모리에는 네이티브 코드 형식으로 구성된 명령어와 데이터가 저장된다.
CPU는 메모리로부터 명령어나 데이터를 읽어 CPU의 내부에 있는 레지스터에 저장한 후 처리한다.

05. 어셈블리어에서 가장 많이 사용하는 mov 명령어

명령어 중에서 레지스터나 메모리에 값을 저장할 수 있는 mov 명령어가 가장 많이 사용된다.

06. push와 pop으로 데이터 저장, 읽기를 해결하는 스택

프로그램이 실행될 때는 스택이라는 데이터 영역이 메모리에 확보된다.
스택은 일시적으로 사용되는 데이터가 저장되는 임시 저장 영역으로 push와 pop으로 데이터를 저장하고 읽어 내는 특징을 가지고 있다.
x86 계열 32비트 CPU에서는 1회의 push 또는 pop으로 32비트 길이의 데이터를 다룰 수 있다.
이 명령어들에는 오퍼랜드가 하나만 있는데 이는 무엇을 처리하는 가를 나타낸다.

07. 함수 호출의 원리를 낱낱이 밝혀 보자!

함수 호출 작업에서는 스택이 사용된다.
어셈블리어 소스 코드를 보면 뒤에 있는 매개변수부터 차례로 스택에 저장되고 함수를 호출한다.
어셈블리어에서 함수명은 함수가 있는 메모리 어드레스를 나타낸다.

08. 쿵탕쿵탕! 함수의 내부에서 이뤄지는 작업들

호출 전 ebp 레지스터를 이미 사용했을 가능성이 있으므로 함수 내부에서 사용하는 레지스터는 함수 호출 전의 상태로 되돌릴 수 있도록 스택에 저장해서 보관한다. 그런 다음 처리가 끝나기 직전 pop을 통해 원상복구한다.
스택의 주소를 관리하고 있는 esp 레지스터의 값을 ebp 레지스터에 저장하고 주소를 사용해 매개변수들을 참조하여 함수를 처리한다.
이후 ret 명령어가 실행되면 스택으로부터 함수가 실행을 끝내고 돌아가야할 곳으로 메모리 주소가 자동으로 팝된다.

09. 글로벌 변수를 위한 영역은 언제나 확보되어 있다!

C언어에서는 함수의 외부에 정의된 변수를 글로벌 변수라하고 함수 안에 선언된 변수를 로컬 변수라 한다.
볼랜드 C++에서 초기화된 글로벌 변수는 _DATA라는 세그먼트로 정리되고 초기화되어있지 않은 글로벌 변수는 _BSS 세그먼트로 정리된다.
이처럼 글로벌 변수를 위한 영역이 확실히 확보가 되어있으므로 프로그램의 생명주기 동안 글로벌 변수를 참조할 수 있다.

10. 로컬 변수를 위한 영역은 일시적으로 확보된다!

로컬 변수를 참조하는 작업은 그 변수가 선언된 함수 안에서만 가능하다. 이 이유는 로컬 변수가 레지스터나 스택을 통해 일시적으로 확보되기 때문이다.

11, 12, 13은 집중 잘 될때 다시 한번 더