[Reversing] assembly 명령어, 레지스터, 메모리 구조

‍허진·2023년 3월 21일
0

hacking

목록 보기
2/7

어셈블리어(Assembly language)는 컴퓨터 프로그래밍 언어 중 하나로, 기계어(Machine language)를 기반으로 한 낮은 수준의 프로그래밍 언어이다. 기계어는 0과 1로 이루어져 있어서 사람이 직접 작성하기 어렵고 이해하기 어렵기 때문에, 어셈블리어는 기계어에 대한 추상화된 형태의 표현으로 각 명령어들이 어떤 기능을 수행하는지 이해하기 쉽도록 만들어졌다.

어셈블리어 명령어는 기본적으로 CPU가 수행하는 명령어와 일대일로 대응된다. 이 명령어들은 각각 두 부분으로 이루어져 있다. 첫 번째 부분은 명령어 코드(opcode)로, 이 명령어가 어떤 기능을 수행하는지를 나타내는 부분이다. 두 번째 부분은 피연산자(operand)로, 이 명령어가 작업을 수행할 데이터나 메모리 주소를 나타내는 부분이다.

어셈블리 명령어의 종류에는 다음과 같은 것들이 있다.

mov : 데이터를 레지스터나 메모리에 복사한다.

add/sub : 덧셈/뺄셈을 수행한다.

imul/mul : 정수 곱셈을 수행한다. 각각 부호 있는, 부호 없는 곱셈이다.

idiv/div : 정수 나눗셈을 수행한다. 각각 부호 있는, 부호 없는 나눗셈이다.

shr/shl : 비트 단위 시프트 연산을 수행한다.

cmp : 비교를 수행한다. 

jmp : 분기를 수행한다. (무조건)

je/jne/jg/jl : 조건 분기를 수행한다.

call : 서브루틴(ex.함수)을 호출한다.

ret : 서브루틴에서 복귀한다.

push/pop : 스택에 값을 넣거나 꺼낸다.

xor/and/or : 비트 단위 연산을 수행한다.

lea : 주소 계산을 수행한다.

레지스터는 컴퓨터의 중앙 처리 장치(CPU) 내부에 있는 데이터 저장 공간이다. 레지스터는 고속으로 액세스할 수 있으며, 프로그램 실행 도중에 사용되는 중요한 데이터나 명령을 저장하고 처리하는 데 사용된다.

자주 쓰이는 레지스터의 이름과 용도는 다음과 같다.

RAX :  Accumulator로 사용되며, 산술 연산을 수행하는 데에 자주 사용된다.

RBX : 베이스 레지스터로 사용되며, 메모리 주소 계산에 자주 사용된다.

RCX : 카운터로 사용되며, 반복문 등에서 반복 횟수를 저장하고, 함수 인수 전달 등에도 사용된다.

RDX : 데이터 레지스터로 사용되며, 입출력 명령어에서 데이터를 전달하거나, 산술 연산을 수행할 때 사용된다.

RSI : 소스 인덱스로 사용되며, 메모리 복사 등에서 복사할 데이터의 시작 주소를 저장한다.

RDI : 대상 인덱스로 사용되며, 메모리 복사 등에서 복사한 데이터를 저장할 시작 주소를 저장한다.

RBP : 베이스 포인터로 사용되며, 함수 호출 시 스택 프레임의 시작 주소를 저장한다.

RSP : 스택 포인터로 사용되며, 현재 스택의 최상위 주소를 저장한다.

R8 ~ R15 : 함수 인수 전달 등에 사용된다.

함수의 호출과 관련해서는 다음과 같은 순서로 진행된다.

  1. 함수 호출 전, 호출하는 측에서 인수를 레지스터에 저장한다. 이때 순서는 RDI, RSI, RDX, RCX, R8, R9 순서로 저장하고, 남는 건 스택에 push한다.
  2. 스택 포인터(RSP)를 조정한다.
  3. 함수 호출 시 레지스터에 저장된 인수와 스택에 저장된 인수를 순서대로 호출 대상 함수에 전달한다.
  4. 함수가 반환될 때, 반환 값은 RAX 레지스터에 저장한다.
  5. RSP 레지스터를 이용하여 스택 프레임을 정리한다. 이를 통해 호출한 함수와 호출 대상 함수 간에 스택 프레임이 서로 겹치지 않도록 한다.
  6. 호출한 함수는 RAX 레지스터에 저장된 반환 값을 이용하여 다음 작업을 수행한다.

컴퓨터의 메모리 구조는 다음과 같다.

[이미지 출처 - https://velog.io/@yeahg_dev]

  1. code 영역 : 프로그램의 실행 가능한 코드가 저장된다. read-only 영역으로 변경이 불가능하다.
  2. data 영역 : 전역 변수와 정적 변수를 저장한다. 세부적으로 initialized data와 non-initialized data로 나누기도 한다.
  3. heap 영역 : 동적 할당을 위한 메모리 공간이다. 프로그램이 runtime 동안 동적으로 할당하여 저장할 수 있다.
  4. stack 영역 : 지역 변수와 함수의 매개변수를 저장하는 공간이다.

code, data, heap 영역은 데이터가 낮은 주소부터 쌓이지만, stack 영역은 높은 주소에서부터 거꾸로 쌓인다는 특징이 있다.

profile
매일 공부하기 목표 👨‍💻 

0개의 댓글