3. Data-Related Operators and Directives
1) OFFSET (Operator)
1> byte나 label이 data segment로부터 떨어진 byte 수를 알려준다.
2> 특징
- Protected mode: 32bit / Real mode: 16bits
- Protected mode 프로그램은 하나의 세그먼트만 사용함 (flat memory model)
3> 예시
.data
bVal BYTE ? ; 1byte
wVal WORD ? ; 2byte
dVal DWORD ? ; 4byte
dVal2 DWORD ? ; 4byte
; Assume that the data segment begins at 00404000h.
.code
mov esi,OFFSET bVal ; ESI = 00404000
mov esi,OFFSET wVal ; ESI = 00404001 (그 앞에 존재하는 bVal이 1byte이므로)
mov esi,OFFSET dVal ; ESI = 00404003 (그 앞에 존재하는 wVal이 2byte이므로)
mov esi,OFFSET dVal2 ; ESI = 00404007 (그 앞에 존재하는 dVal이 4byte이므로)
4> OFFSET은 C언어의 pointer와 유사하다.
- C언어
char array[1000];
char *p = array;
- 어셈블리어
.data
array BYTE 1000 DUP(?)
.code
mov esi, OFFSET array
2) PTR (Operator)
1> 자료형을 변환(override)한다.
- 기존에 MOV만으로는 size mismatch로는 할당이 불가능했는데
- PTR을 이용하면 형변환을 하기 때문에 size가 달라도 size를 맞춰서 형변환을 하면 할당이 가능하다.
2> 사용
type PTR operand : operand를 type 자료형으로 바꿔준다.
3> Little Endian Order
- 1byte (16진수에서 2자리)이상의 data는 메모리의 역순으로 저장된다.
- CPU는 자동으로 byte들을 뒤집어서 저장한다,
- 그래서 아래 예시의 code line 2와 line 3과 같은 현상이 일어난다.
4> 예시 1
.data
myDouble DWORD 12346578h
.code
mov ax, myDouble ; size mismatch
mov ax, WORD PTR myDouble ; loads 5678h
mov ax, WORD PTR [myDouble+2] ; loads 1234h
mov WORD PTR myDouble, 4321h ; saves 4321h
5> 예시 2
data
myDouble DWORD 12345678h
.code
mov al, BYTE PTR myDouble ; AL = 78h
mov al, BYTE PTR [myDouble + 1] ; AL = 56h
mov al, BYTE PTR [myDouble + 2] ; AL = 34h
mov ax, WORD PTR myDouble ; AX = 5678h
mov ax, WORD PTR [myDouble + 1] ; AX = 1234h
6> 예시 4
- array 형태로 저장해도 little endian order가 적용된다.
.data
myBytes BYTE 12h, 34h, 56h, 78h
.code
mov ax, WORD PTR [myBytes] ; AX = 3412h
mov ax, WORD PTR [myBytes + 2] ; AX = 7856h
mov eax, DWORD PTR myBytes ; EAX = 78563412h
7> 예시 5
.data
varB BYTE 65h, 31h, 02h, 05h
varW WORD 6543h, 1202h
varD DWORD 12345678h
.code
mov ax, WORD PTR [varB + 2] ; a. 0502h
mov bl, BYTE PTR varD ; b. 78h
mov bl, BYTE PTR [varW + 2] ; c. 02h
mov ax, WORD PTR [varD + 2] ; d. 1234h
mov eax, DWORD PTR varW ; e. 12026543h
3) TYPE (Operator)
1> 하나의 데이터 요소의 크기를 byte 수로 알려준다.
2> 사용
TYPE operand : operand의 byte 수를 의미
3> 예시
.data
var1 BYTE ?
var2 WORD ?
var3 DWORD ?
var4 QWORD ?
.code
mov eax, TYPE var1 ; 1
mov eax, TYPE var2 ; 2
mov eax, TYPE var3 ; 4
mov eax, TYPE var4 ; 8
4) LENGTHOF (Operator)
1> 하나의 데이터에 들어있는 element의 개수를 알려준다.
2> 사용
LENGTHOF operand : operand 내부에 들어있는 element의 개수
3> 예시
.data ; LENGTHOF
byte1 BYTE 10, 20, 30 ; 3
array1 WORD 30 DUP(?), 0, 0 ; 32
array2 WORD 5 DUP(3 DUP(?)) ; 15
array3 DWORD 1, 2, 3, 4 ; 4
digitStr BYTE "12345678", 0 ; 9
.code
mov ecx, LENGTHOF array1 ; 32
5) SIZEOF (Operator)
1> 하나의 데이터 전체 크기를 알려준다.
- LENGTHOF과 TYPE를 곱한 것과 같다.
2> 사용
SIZEOF operand : operand의 전체 크기를 알려준다.
3> 예시
.data ; SIZEOF
byte1 BYTE 10, 20, 30 ; 3
array1 WORD 30 DUP(?), 0, 0 ; 64
array2 WORD 5 DUP(3 DUP(?)) ; 30
array3 DWORD 1, 2, 3, 4 ; 16
digitStr BYTE "12345678", 0 ; 9
.code
mov ecx, LENGTHOF array1 ; 64
cf> Spanning Multiple Lines
- comma(,)로 늘여쓰는 것 같은 원소로 인식한다.
- attribute(WORD와 같은 자료형) 옆에 있는 것만 원소로 인식한다. (즉, attribute가 자료를 끊어주는 것 같다고 생각)
.data
array WORD 10,20,
30, 40
array1 WORD 50, 60
WORD 70, 80
.code
mov eax,LENGTHOF array ; 4
mov ebx,SIZEOF array ; 8
mov eax,LENGTHOF array1 ; 2
mov ebx,SIZEOF array1 ; 4
6) LABEL (Directive)
1> 각 자료형으로의 접근을 새로운 이름으로 만든다.
- 데이터에 접근할 때 PTR을 사용하지 않아도 된다.
2> 사용
label_name LABEL TYPE : 해당 TYPE으로 아래 '다른 data'를 label_name으로 접근 가능하다.
다른 data 선언
3> 예시
.data
dwList LABEL DWORD
wordList LABEL WORD
intList BYTE 00h, 10h, 00h, 20h
.code
mov eax, dwList ; 20001000h
mov cx, wordList ; 1000h
mov dl, intList ; 00h
- mov eax, dwList : intList를 DWORD로 접근할 수 있다.
- mov eax, wordList : intList를 WORD로 접근할 수 있다.
- mov dl, intList : MSB에 위치한 00h만 레지스터로 이동할 수 있다.