[libasm] Assembly - 주소 지정 모드(Addressing Modes)

Park Sejin·2021년 3월 31일
0
post-thumbnail

대부분의 어셈블리어 명령어는 처리할 피연산자가 필요하다. 피연산자 주소는 처리할 데이터가 저장된 위치를 제공한다. 일부 명령어는 피연산자가 필요 없지만, 다른 일부 명령어들은 한 개, 두 개, 또는 세 개의 피연산자가 필요하다.

명령어가 두 개의 피연산자를 필요로 할 경우, 일반적으로 첫 번째 피연산자는 목적지(destination) 이고 두 번째 피연산자는 원본(source) 이다. 목적지는 레지스터 또는 메모리의 데이터를 담고 있다. 그리고 원본은 전달되는 데이터(즉시 주소 지정(Immediate addressing))나 데이터의 주소(레지스터 또는 메모리)를 담고 있다. 일반적으로 원본 데이터는 연산 후에 변경되지 않는다.

주소 지정에는 세 가지 기본 모드가 있다.

  • 레지스터 주소 지정(Register addressing)
  • 즉시 주소 지정(Immediate addressing)
  • 메모리 주소 지정(Memory addressing)

레지스터 주소 지정(Register Addressing)

레지스터 주소 지정 방식에서는 레지스터가 피연산자이다. 명령어에 따라, 레지스터가 첫 번째 피연산자가 되거나, 두 번째 피연산자가 되거나 둘 다가 될 수 있다.

예를 들어,

MOV DX, TAX_RATE	; 첫 번째 피연산자가 레지스터
MOV COUNT, CX		; 두 번째 피연산자가 레지스터
MOV EAX, EBX		; 두 피연산자가 모두 레지스터

레지스터 사이의 연산은 메모리에 접근하지 않으므로 가장 빠른 데이터 연산 속도를 제공한다.

즉시 주소 지정(Immediate Addressing)

직접 피연산자는 상수나 표현식을 가진다. 명령어가 두 개의 피연산자를 즉시 주소 지정 방식으로 사용할 때, 첫 번째 피연산자는 레지스터이거나 메모리 위치이고 두 번째 피연산자는 상수다. 첫 번째 피연산자는 데이터의 길이를 정의한다.

예를 들어,

BYTE_VALUE DB 150	; BYTE_VALUE가 정의됨
WORD_VALUE DW 300	; WORD_VALUE가 정의됨
ADD BYTE_VALUE, 65	; 직접 피연산자 65가 더해짐
MOV AX, 45H		; 상수 45H가 AX로 전달됨

직접 메모리 주소 지정(Direct Memory Addressing)

피연산자가 메모리 주소 지정 방식으로 지정되면 메모리 직접 접근(주로 data 세그먼트로 직접 접근)이 필요하다. 이 주소 지정 방식은 데이터 처리 속도가 느리다. 메모리 내의 정확한 데에터 위치를 파악하기 위해서, 세그먼트의 시작 주소가 필요하다. 세그먼트의 시작 주소는 DS 레지스터와 오프셋 값으로 알아낼 수 있다. 오프셋 값은 effective address로 불린다.

직접 주소 지정 모드에서 오프셋 값은 명령어의 일부로 직접 지정된다. 어셈블러는 오프셋 값을 계산하고 프로그램에서 사용하는 모든 변수의 오프셋 값이 저장된 심볼 테이블을 관리한다.

직접 주소 지정 모드에서 피연산자 중 하나는 메모리의 위치를 참조하고 다른 하나는 레지스터를 참조한다.
예를 들어,

ADD BYTE_VALUE, DL 	; BYTE_VALUE 메모리 위치에 DL 레지스터를 ADD한다.
MOV BX, WORD_VALUE 	; 메모리에 있는 피연산자 WORD_VALUE가 BX 레지스터에 저장된다.

직접 오프셋 주소 지정(Direct-Offset Addressing)

직접 오프셋 주소 지정 방식은 주소를 조작하기 위해 산술 연산자를 사용한다. 예를 들어, 아래의 데이터 테이블 정의를 보자.

BYTE_TABLE DB	14, 15, 22, 45		; bytes 테이블
WORD_TABLE DW	134, 345, 564, 123	; words 테이블

아래의 연산은 메모리 내에 있는 테이블의 데이터에 접근하여 레지스터로 저장한다.

MOV CL, BYTE_TABLE[2]	; BYTE_TABLE의 세 번째 원소의 값을 얻는다.
MOV CL, BYTE_TABLE + 2	; BYTE_TABLE의 세 번째 원소의 값을 얻는다.
MOV CX, BYTE_TABLE[3]	; BYTE_TABLE의 네 번째 원소의 값을 얻는다.
MOV CX, BYTE_TABLE + 3	; BYTE_TABLE의 네 번째 원소의 값을 얻는다.

간접 메모리 주소 지정(Indirect Memory Addressing)

간접 메모리 주소 지정 방식은 Segment:Offset 주소 지정 방식을 활용한다. 일반적으로 베이스 레지스터 EBX, EBP (또는 BX, BP)와 인덱스 레지스터 DI, SI는 대괄호를 사용(메모리 참조가 가능)하면 이런 목적으로 사용할 수 있다.

간접 주소 지정 방식은 일반적으로 배열과 같은 여러개의 원소를 포함하는 변수에 사용한다. 배열의 시작 주소는 EBX 레지스터에 저장된다.

아래의 코드는 변수의 원소들에 접근하는 방식을 보여준다.

MY_TABLE TIMES 10 DW 0	; 워드(2바이트) 크기의 공간 10개를 모두 0으로 초기화하여 할당한다.
MOV EBX, [MY_TABLE]	; MY_TABLE의 effective address를 EBX로 저장한다.
MOV [EBX], 110		; MY_TABLE[0] = 110
ADD EBX, 2		; EBX = EBX + 2
MOV [EBX], 123		; MY_TABLE[1] = 123

MOV 명령어

이미 MOV 명령어를 사용했다. MOV 명령어는 어떤 저장 공간에서 다른 저장 공간으로 데이터를 옮기는데 사용한다. MOV 명령어는 두 개의 피연산자를 받는다.

MOV 명령어의 구문은 다음과 같다

MOV 목적지, 원본

MOV 명령어는 다섯 가지 형태 중 하나를 가진다.

MOV register, register
MOV register, immediate
MOV memory, immediate
MOV register, memory
MOV memory, register

아래의 항목을 주의해야 한다.

  • MOV 명령의 두 피연산자는 같은 크기여야 한다.
  • 원본 피연산자의 값은 변경되지 않는다.

MOV 명령어는 때때로 모호성을 유발한다. 예를 들어, 아래의 코드를 보자.

MOV EBX, [MY_TABLE]	; MY_TABLE의 effective address를 EBX에 저장한다.
MOV [EBX], 110		; MY_TABLE[0] = 110

숫자 110의 바이트 크기를 이동하는지 워드 크기를 이동하는지 명확하지 않다. 타입 지정자(type specifier)를 사용하는 것이 좋다.

아래의 테이블은 일반적인 타입 지정자를 나타낸다.

Type SpecifierBytes addressed
BYTE1
WORD2
DWORD4
QWORD8
TBYTE10

예를 들어
아래의 프로그램은 위에서 다룬 개념들을 설명하고 있다. 메모리의 데이터 섹션에 이름 'Zara Ali'를 저장한 후, 다른 이름인 'Nuha Ali'로 값을 변경한다. 그리고 두 이름을 출력한다.

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

section .text
	global _main
_main:

	mov	rdx, 9
	mov	rsi, name
	mov	rdi, 1
	mov	rax, 0x2000004
	syscall

	;mov	[name],	dword 'Nuha' ; 원래의 코드는 64비트에서 실행되지 않는다.
	mov	r10, name	     ; 64비트 macOS에서는 32비트 절대 주소 접근방식을 지원하지 않는다고 해서
	mov	[r10], dword 'Nuha'  ; r10 레지스터에 name의 주소를 저장하고 r10 레지스터를 통해 name의 값을 변경했다.

	mov	rdx, 8
	mov	rsi, name
	mov	rdi, 1
	mov	rax, 0x2000004
	syscall

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

section .data
	name db 'Zara Ali '

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

Zara Ali Nuha Ali

출처

tutorialspoint.com

0개의 댓글