본문 바로가기

Hardware/assembly language

4장(데이터 전송, 주소지정과 산술연산)

피연산자 유형

직접 오프셋 피연산자

.data

arrayB BYTE 10h,20h,30h,40h,50h

.code

mov al, arrayB ;10h

mov al.[arrayB+1] ;20h

arrayB+1 과 같은 수식은 상수를 변수의 오프셋에 더하여 유효 주소 라고 하는 것을 계산해낸다.

유효 주소를 대괄호로 둘러쌓은 것은 그 주소의 메모리 내용을 얻기 위하여 주소 수식을 역참조 함을 나타낸다.

MASM 에서는 대괄호가 필수 사항은 아니다.

mov al, arrayB+1 = mov al,[arrayB+1]

.data

arrayW WORD 100h, 200h, 300h

.code

Mov ax, arrayW ;100h

Mov ax, [arrayW+2] ;200h

 

.data

arrayD DWORD 10000h,20000h

.code

Mov eax ,arrayD ;10000h

Mov eax, [arrayD+4] ;20000h

7판에는 CPU Debugger 추가

4.3 데이터 관련 연산자와 디렉티브

OFFSET 연산자 세그먼트의 시작으로 부터의 변수의 거리를 반환한다.

PTR 연산자는 변수의 선언된 기본 크기를 바꾸어서 사용할 수 있게 한다

TYPE 연산자는 피연산자 또는 배열의 각 원소의 크기를 반환한다.

LENGTHOF 연산자는 배열의 원소의 개수를 반환한다.

SIZEOF 연산자는 배열의 초기값이 설정된 바이트 수를 반환한다.

 

OFFSET 연산자

ALIGN 디렉티브

ALIGN 디렉티브는 변수를 바이트, 워드 ,더블워드 또는 문단의 경계에 정렬한다.

ALIGN bound

왜 귀찮게 데이터를 정렬하는가? CPU는 홀수 주소에 저장된 데이터 보다는 짝수 주소에 저장된 데이터를 더 빠르게 처리 할 수 있다.

왜 빠르게 처리 할 수 있냐 하면 데이터 버스가 짝수 비트로 되어 있기 때문.(8086은 16비트 데이터 버스) Windows 구조와 원리 그

리고 Codes 2장에 자세히 설명되어 있다

예시

PTR 연산자

피연산자의 선언된 크기를 바꾸어 샤용하기 위해서 PTR 연산자를 사용 할 수 있다.

ERROR 코드

동작 코드

mov ax, WORD PTR myDouble ;5678h

TYPE 연산자

LENGTHOF 연산자

레이블과 같은 줄에 있는 값들로 정의 되어있는 배열에 있는 원소의 개수를 반환한다.

SIZEOF 연산자

SIZEOF 연산자는 LENGTHOF와 TYPE을 곱한 값을 반환한다.

LABEL

저장공간을 할당하지 않으면서 레이블을 넣고 그것에 크기 속성을 주게 한다

LABEL의 일반적인 용도는 데이터 세그먼트에서 다음에 선언된 변수에 대해서 다른 이름과 크기 속성을 제공하는 것이다.

Val16은 val32라는 이름의 저장공간에 대한 별명이다. LABEL 디렉티브는 어떠한 저장공간도 할당하지 않는다.

간접 주소 지정

보호모드:

보호모드에서 간접 피연산자는 대괄호를 둘러싸인 임의의 32비트 범용 레지스터(EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP) 일 수 있다.

다음 예에서 ESI는 byteVal의 오프셋을 참조한다.

MOV 명령어는 간접 피연산자를 소스로 사용하고 ESI에 있는 오프셋이 역참조되어 바이트가 AL로 이동한다.

목적지 피연산자가 간접 주소지정을 사용한다면 새로운 값이 레지스터가 가리키는 위치에 있는 메모리에 저장된다.

다음 예에서 BL 레지스터의 내용은 ESI로 주소 지정되는 메모리 위치로 복사된다.

Mov [esi] , bl

실제 주소모드:

실제 주소모드에서는 16비트 레지스터에 변수의 오프셋을 저장한다.

레지스터가 간접 피연산자로 사용된다면 SI,DI,BX,BP 만 사용한다 BP는 데이터 세그먼트가 아닌 스택의 주소로 지정되기 때문에 사용을 피하자.

배열

8비트 배열

16비트

포인터

다른 변수의 주소를 포함하는 변수를 포인터라고 한다.

포인터는 배열과 자료구조를 다루기 위한 훌륭한 도구이고 동적 메모리 할당을 가능하게 한다.

X86 프로그램은 NEAR와 FAR의 두가지의 기본 유형의 포인터를 사용한다.

Near_pointer=0x1234; //옵셋 0x1234

Far_pointer=0x20001234L; //0x2000 세그먼트, 옵셋 0x1234

TYPE 연산자 사용

TYPEDEF 연산자는 사용자 정의 자료형을 만들 수 있게 한다.

사용자 정의 자료형은 변수의 정의 할 때에 내장된 자료형의 모든 지위를 갖는다.

TYPEDEF는 포인터 변수를 만드는데 이상적이다.

JMP 명령어

LOOP 명령어

실제 주소 모드에서는 CX가 LOOP 명령어에 대한 기본 루프 카운터이다.

위 코드는 ECX 가 계속 증가하여 루프가 멈추지 않는다.

ARM assembly

While(1)

{

Printf(hellow assembly”);

Printf(hellow assembly2”);

 

}

ARM assembly 에서는 그냥 무조건 분기 명령어로 다시 0x800277a로 돌아가라고 함

따라서 while(1) 자체에는 breakpoint가 잡히지 않는다

 

R0에 hellow assembly가 들어가 있는 메모리 주소를 적어 놓고 printf 로 들어간다.

'Hardware > assembly language' 카테고리의 다른 글

5장(프로시저)  (0) 2019.12.22
3장(어셈블리 언어의 기초)  (0) 2019.12.22
2장(x86 프로세서 구조)  (0) 2019.12.22
1장(기본 개념)  (0) 2019.12.22