[libasm] Assembly - 레지스터

Park Sejin·2021년 3월 28일
1
post-thumbnail

프로세서 동작은 대부분 데이터 처리와 관련이 있다. 이 데이터는 메모리에 저장되고 메모리에서 불러올 수 있다. 하지만, 메모리에서 데이터를 읽고 저장하는 것은 데이터 요청을 컨트롤 버스와 메모리 스토리지 유닛으로 보내고 다시 같은 채널을 통해 데이터를 받는 복잡한 처리를 하기 때문에 프로세서를 느리게 한다.

프로세서 동작을 빠르게 하기 위해, 프로세서는 레지스터라는 내부 메모리 저장 공간을 가지고 있다.

레지스터는 메모리에 접근하지 않고 처리할 데이터를 저장한다. 프로세서 칩에 한정된 수의 레지스터들이 내장되어 있다.

프로세서 레지스터

IA-32 아키텍처에는 32비트 10개, 16비트 6개의 프로세서 레지스터가 존재한다. 이 레지스터는 세 가지로 분류된다.

  • 범용 레지스터
  • 컨트롤 레지스터
  • 세그먼트 레지스터

범용 레지스터는 다시 다음과 같이 분류된다.

  • 데이터 레지스터
  • 포인터 레지스터
  • 인덱스 레지스터

데이터 레지스터

네 개의 32비트 데이터 레지스터는 산술, 논리 그리고 다른 작업을 위해 사용된다. 이 데이터 레지스터는 세 가지 방식으로 사용할 수 있다.

  • 완전한 32비트 데이터 레지스터 : EAX, EBX, ECX, EDX

  • 32비트 레지스터의 아래쪽 절반은 네 개의 16비트 데이터 레지스터로 사용할 수 있다.: AX, BX, CX, DX

  • 16비트 레지스터의 아래쪽 절반과 위쪽 절반은 여덟 개의 8비트 데이터 레지스터로 사용할 수 있다.: AH, AL, BH, BL, CH, CL, DH, DL


    이 데이터 레지스터들 중 일부는 산술 연산을 위한 특정한 용도가 있다.
    AX는 누산기이다. 입출력과 대부분의 산술 연산을 처리한다.
    BX는 베이스 레지스터이다. 주소 연산에 사용된다.
    CX는 카운터 레지스터이다. 반복적인 작업에서 루프 카운터를 저장한다.
    DX는 데이터 레지스터이다. 입출력 작업에 사용하고 AX와 같이 산술연산을 처리한다.

포인터 레지스터

포인터 레지스터는 32비트 EIP, ESP, EBP 레지스터와 하위 16비트 부분인 IP, SP, BP 레지스터가 있다. 포인터 레지스터는 세 가지로 분류된다.

  • Instruction Pointer(IP) : 16비트 IP 레지스터는 실행되는 다음 명령어의 오프셋 주소를 저장한다. IP는 CS 레지스터와 함께 사용하여(다음과 같이 CS:IP) 코드 세그먼트에서 현재 명령어의 완전한 주소를 표현한다.

  • Stack Pointer(SP) : 16비트 SP 레지스터는 프로그램 스택 내에서 오프셋 값을 제공한다. SP는 SS 레지스터와 함께 사용하여(다음과 같이 SS:SP) 데이터의 현재 위치나 프로그램 스택 내에서 주소를 참조한다.

  • Base Pointer(BP) : 16비트 BP 레지스터는 주로 서브루틴에 전달되는 매개변수를 참조하는데 사용된다.

인덱스 레지스터

32비트 ESI, EDI와 오른쪽 16비트 부분 SI, DI가 인덱스 레지스터다. 이 레지스터들은 주소 연산에 사용하고, 가감 연산에도 사용할 수 있다. 두 가지의 인덱스 포인터가 존재한다.

  • Source Index(SI) : 문자열 처리를 위한 소스 인덱스로 사용된다.
  • Destination Index(DI) : 문자열 처리를 위한 목적지 인덱스로 사용된다.

컨트롤 레지스터

32비트 명령어 포인터 레지스터와 32비트 플래그 레지스터는 합쳐서 컨트롤 레지스터로 간주된다.

많은 명령어들은 비교, 산술 연산과 관련이 있고, 플래그의 상태를 변화시킨다. 몇 가지 다른 조건 명령어는 제어 흐름을 다른 위치로 가져가기 위해 상태 플래그의 값을 테스트 한다.

일반적인 플래그 비트는 다음과 같다.

  • Over Flag(OF)
  • Direction Flag(DF)
  • Interrupt Flag(IF)
  • Trap Flag(TF)
  • Sign Flag(SF)
  • Zero Flag(ZF)
  • Auxiliary Carry Flag(AF)
  • Parity Flag(PF)
  • Carry Flag(CF)

다음 표는 16비트 플래그 레지스터에서 플래그 비트들의 위치를 나타낸다.

Flag:ODITSZAPC
Bit no:1514131211109876543210

세그먼트 레지스터

세그먼트는 프로그램에 사용하기 위해 데이터, 코드, 스택을 포함하여 정의된 특정 영역이다. 세그먼트는 세 가지 주 세그먼트로 나뉜다.

  • Code 세그먼트 : 실행되는 모든 명령어가 담긴다. 16비트 Code 세그먼트 레지스터 또는 CS 레지스터는 Code 세그먼트의 시작주소를 저장한다.
  • Data 세그먼트 : 데이터, 상수, 작업영역이 담긴다. 16비트 Data 세그먼트 레지스터 또는 DS 레지스터는 Data 세그먼트의 시작주소를 저장한다.
  • Stack 세그먼트 : 프로시져 또는 서브루틴의 반환주소와 데이터가 담긴다. '스택' 자료 구조로 구현되어 있다. Stack 세그먼트 레지스터 또는 SS 레지스터는 스택의 시작주소를 저장한다.

DS, CS, SS 레지스터와는 별개로 추가 세그먼트 레지스터가 존재한다. ES(extra segment), FS, GS와 같은 세그먼트들은 데이터 저장을 위한 추가 세그먼트이다.

예제

아래의 코드는 어셈블리 프로그래밍에서 레지스터의 사용을 이해하기 위한 간단한 예제이다. 이 프로그램은 9개의 별을 메세지와 함께 출력한다.

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

section .text
	global _main		; 링커가 알 수 있도록 반드시 선언해주어야 한다.

_main:				; 시작점을 링커에 알려준다.
	mov	rdx, len	; 메세지 길이를 rdx 레지스터에 저장한다.
	mov	rsi, msg	; 출력할 메세지를 rsi 레지스터에 저장한다.
	mov	rdi, 1		; rdi 레지스터에 파일 디스크립터를 1(표준출력)로 저장한다.
	mov	rax, 0x2000004	; rax 레지스터에 write 시스템콜을 저장한다.
	syscall			; write 시스템콜을 호출한다.

	mov	rdx, 9		; 별 문자열의 길이를 rdx 레지스터에 저장한다.
	mov	rsi, s2		; 출력할 별 문자열을 rsi 레지스터에 저장한다.
	mov	rdi, 1		; rdi 레지스터에 파일 디스크립터를 1(표준출력)로 저장한다.
	mov	rax, 0x2000004	; rax 레지스터에 write 시스템콜을 저장한다.
	syscall			; write 시스템콜을 호출한다.

	mov	rax, 0x2000001	; rax 레지스터에 exit 시스템콜을 저장한다.
	mov	rdi, 0		; exit 함수의 파라미터에 0을 저장한다.
    				; 그렇지 않으면 프로그램 종료 시 exit code를 리턴한다.
	syscall			; exit 시스템콜을 호출한다.

section .data
	msg db 'Displaying 9 stars', 0xa ; 출력할 메세지
	len equ $ - msg			 ; 메세지의 길이
	s2 times 9 db '*'		 ; 출력할 별 문자열

위의 코드를 컴파일하고 실행하면 아래의 결과를 얻을 수 있다.

Displaying 9 stars
*********

출처

tutorialspoint.com

0개의 댓글