[libasm] Assembly - 프로시저

Park Sejin·2021년 4월 14일
0

[libasm] nasm 어셈블러

목록 보기
12/12
post-thumbnail

어셈블리어 프로그램은 크기가 큰 경향이 있으므로 프로시저 또는 서브루틴은 어셈블리어에서 매우 중요하다. 프로시저는 이름으로 구분된다. 가장 먼저 프로시저 이름을 쓰고, 다음에 프로시저가 수행할 작업이 기술된 프로시저 바디를 작성한다. 마지막으로 return문으로 프로시저의 끝을 표시한다.

구문

프로시저를 정의하는 구문은 다음과 같다.

proc_name:
	procedure body
	...
	ret

프로시저는 CALL 명령어를 사용하여 다른 함수에서 호출할 수 있다. CALL 명령어는 호출하고자 하는 프로시저의 이름을
인자로 받아야 한다.

CALL proc_name

호출된 프로시저는 RET 명령어로 호출한 프로시저에게 제어권을 반환한다.

예제

아주 간단한 sum 프로시저를 작성한다. sum 프로시저는 ECX, EDX 레지스터에 저장된 변수를 add하고 EAX 레지스터로 합을 반환한다.

❗️ 64비트 Intel macOS에서 동작하는 코드이다.

section .text
	global _main

_main:
	mov	ecx, '4'
	sub	ecx, '0'

	mov	edx, '5'
	sub	edx, '0'

	call sum	; sum 프로시저 호출
	mov	r10, res
	mov	[r10], eax
	mov	rsi, msg
	mov	rdx, len
	mov	rdi, 1
	mov	rax, 0x2000004
	syscall

	mov	rsi, res
	mov	rdx, 1
	mov	rdi, 1
	mov	rax, 0x2000004
	syscall

	mov	rax, 0x2000001
	mov	rdi, 0
	syscall

sum:
	mov	eax, ecx
	add	eax, edx
	add	eax, '0'
	ret

section .data
msg	db "The sum is:", 0xA, 0xD
len equ $ - msg

section	.bss
res resb 1

코드를 컴파일하고 실행하면 다음과 같은 결과를 확인할 수 있다.

The sum is:
9

스택 데이터 구조

스택은 메모리 내에 배열과 같은 데이터 구조로 이루어져있다. 스택의 top이라고 불리는 위치를 통해 데이터가 저장되고 삭제된다. 스택에 push하여 데이터를 저장하고 pop하여 데이터를 꺼낸다. 스택은 LIFO 데이터 구조이다. 즉, 먼저 저장된 데이터가 나중에 제거된다.

어셈블리어는 스택의 두 가지 명령어를 제공한다. : PUSH, POP. 이 명령어들의 구문은 다음과 같다.

PUSH operand
POP address/register

스택 세그먼트 안에 할당된 메모리 공간은 실행 스택을 위해 사용된다. 레지스터 SS와 ESP(또는 SP)는 스택을 실행하는데 사용된다. 스택에 삽입된 마지막 데이터를 가리키는 top은 SS:ESP 레지스터로 접근할 수 있다. 여기서 SS 레지스터는 스택 세그먼트의 시작을 가리키고 SP(또는 ESP)는 스택 세그먼트의 오프셋을 의미한다.

스택 실행은 다음의 특징을 가진다.

  • words 또는 doublewords만 스택에 저장할 수 있다. byte는 안된다.
  • 스택은 메모리주소의 반대 방향으로 추가된다. 즉, 높은 메모리 주소에서 낮은 메모리 주소로 스택이 쌓인다.
  • 스택의 top은 스택에 삽입된 마지막 아이템을 가리킨다. 삽입된 마지막 word의 하위 byte을 가리킨다.(Little-Endian)

다른 목적으로 레지스터를 사용하기 전에 스택에 기존 레지스터의 값을 저장한다. 코드는 다음과 같다.

; 스택에 AX, BX 레지스터를 저장한다.
PUSH AX
PUSH BX

; 다른 목적으로 레지스터를 사용한다.
MOV AX, VALUE1
MOV BX, VALUE2
..
MOV VALUE1, AX
MOV VALUE2, BX

; 레지스터를 원래 값으로 되돌린다.
POP BX
POP AX

출처

tutorialspoint.com

0개의 댓글