어셈블리로 메모리에 파일 올라가는 과정

어셈블리언어로 파일을 메모리에 올리는 방법을 알아보기 전에

여기서 말하는 파일(PE파일)이란,

(portable executable)실행파일이라 부르며 흔히 봐왔던 exe파일을 말한다.

 

 

 

출처 https://rninche01.tistory.com/entry/%EC%9C%88%EB%8F%84%EC%9A%B0-%EC%8B%A4%ED%96%89%ED%8C%8C%EC%9D%BC-%EA%B5%AC%EC%A1%B0PE%ED%8C%8C%EC%9D%BC

 

위 사진에서 file이 메모리에 그대로 옮겨짐을 알 수 있는데, 여기서 메모리에 올라가는 데이터는 이것 뿐만 아니라 힙,스택 등 여러가지 정보와 같이 올라가게 된다.

 

 

 

어셈블리언어에서 파일에 정보를 할당하기 위해서 필요한 문법은 c와 순서가 다르다.

변수이름, 크기, 초기값 순서로 변수를 선언해준다.

 

 

크기는 c의 자료형과 같은 개념으로 db(1byte) dw(2) dd(4) dq(8) 각각 해당크기의 공간만큼 할당받을 수 있다.

 

 

예를들어 a라는 변수에 1바이트를 할당하겠다 하면 다음과 같이 선언한다.

section.data
	a dd 0xff

 

 

 

위와 같은 것들은 초기화 된 데이터를 할당할 때 사용할 수 있는 문법이다.

 

초기화를 하지 않는 데이터를 선언하고 싶을 때는 크기를 다르게 설정해줘야 하는데

resb(1) resw(2) resd(4) resq(8) 로 각각의 바이트만큼의 크기를 할당할 수 있다.

section.bss
	b resb 5

 

여기서 b라는 변수에 1바이트만큼의 크기를 할당했는데 그 뒤에 나오는 숫자는 초기값이 아니라 개수를 의미한다.

 

 

 

 

 

 

그런데 왜 굳이 초기화 된 데이터와 초기화 되지 않은 데이터를 구분지어서 저장해야 하나 궁금하다.

 

 

초기화 된 데이터는 그 값을 아까 그림의 exe파일 data영역에 저장해줘야 어떤 값을 초기화 시켰는지 의미를 갖는다.

하지만 초기화 되지 않은 데이터는 자동으로 0이 할당되므로, 그 값의 크기만 알고있으면 굳이 어떤 값이 초기화 됐는지 저장하지 않아도 알 수 있다.

 

이렇게 구분짓는다면, 저장하지 않는만큼 메모리 공간의 효율이 증가하기 때문에 데이터를 따로 구분지어서 저장한다.

 

 

 

그럼 이제 선언한 변수를 레지스터 공간에 할당할 차례이다.

mov rax, [a]

 

위에서 선언한 1바이트짜리 변수 a를 rax라는 8바이트짜리 공간에 mov라는 함수를 사용하여 할당했다.

 

참고로 [ ]표시 없이 그냥 a만 넣는다면 a의 값이 아니라 a의 주소값을 rax저장공간에 넘겨주게 되어 우리가 원하는 값이 나오지 않는다.

 

 

이제 ' mov [a], ' 이후 레지스터 또는 상수값을 입력하게 되는데

레지스터는 바로 넣어도 문제 없지만, 상수값을 입력하는 경우 반드시 상수가 어느정도의 크기를 갖고 있는지 명시해주어야 한다.

 

mov [a], byte 0xff
mov [b], word 0xffff

이와 같이 1바이트를 입력할 것인지, 2바이트를 입력할 것인지 명시해야 한다.

 

[a]의 경우 0xff를 byte없이 입력하면 이 값이 ff값인지, 000000ff인지 구분할 수 없기 때문이다.

 

 

 

그럼 반대로 레지스터를 입력하는 경우는 왜 크기를 입력하지 않아도 되는 것인지에 대한 이유는

rax, eax, al 등등 이미 그 자체로 크기를 의미하고 있기 때문이다.