4. Indirect Addressing
1) Indirect Operands
1> pointer처럼 변수의 주소를 이용해서 접근이 가능하다.
- OFFSET을 이용해서 주소를 찾고
- []를 이용해서 저장된 값을 MOV에 의해 레지스터로 전달된다.
2> 예시 1
(OFFSET val1이 8000이라면)
10h | 20h | 30h |
8000 | 8001 | 8002 |
val1 | val1+1 | val1+2 |
.data
val1 BYTE 10h, 20h, 30h
.code
mov esi, OFFSET val1
mov al, [esi] ; AL = 10h
inc esi
mov al, [esi] ; AL = 20h
inc esi
mov al, [esi] ; AL = 30h
- line 1
- OFFSET을 이용해서 val1의 맨 앞 주소를 파악한다.
- 확실히 esi는 val1의 첫 번째 원소인 BYTE 자료형의 10h를 가리키고 있다.
3> 예시 2
esi가 가리키는 곳이 어떤 자료형인지 모르는 경우 PTR을 사용해야 한다.
.data
myCount WORD 0
.code
mov esi, OFFSET myCount
inc [esi] ; error: ambiguous
int WORD PTR [esi] ; ok
10 | 20 | 30 | 00 | 00 |
8000 | 80001 | 8002 | 8003 | 8004 |
val1 | val1+1 | val1+2 | val1+3 | val+4 |
- 이 경우 val1+3에서 inc연산을 가하면 WORD 단위로 증가할 지 BYTE 단위로 증가할 지 애매해진다.
4> Array Sum Example
.data
arrayW WORD 1000h, 2000h, 3000h
.code
mov esi, OFFSET arrayW
mov ax, [esi]
add esi, 2 ; or: add esi, TYPE arrayW
add ax, [esi]
add esi, 2
add ax, [esi] ; AX = sum of the array
2) Indexed Operands
1> register에 상수를 더해서 effective address를 만들 수 있다.
2> 'label + reg' 와 'label[reg]'는 같은 의미이다.
3> 예시
.data
arrayW WORD 1000h,2000h,3000h
.code
mov esi,0
mov ax, [arrayW + esi] ; AX = 1000h
mov ax, arrayW[esi] ; alternate format
add esi, 2
add ax, [arrayW + esi]
3) Pointers
1> 다른 변수의 OFFSET을 저장하는 포인터 변수를 선언할 수 있다.
2> 예시
.data
arrayW WORD 1000h, 2000h, 3000h
ptrW DWROD arrayW ; alternative format : ptrW DWORD OFFSET arrayW
.code
mov esi, ptrW
mov ax, [esi] ; AX = 1000h
5. JMP and LOOP Instructions
1) JMP (Instruction)
1> 설정한 target으로 점프
2> 사용
JMP target : target으로 jump한다.
3> 예시
top:
.
.
jmp top
4> 현재 procedure 밖의 label로 점프하려면 global label이라는 특별한 type이 필요합니다.
cf> EIP : Instruction Pointer
CPU가 가야할 주소
2) LOOP (Instruction)
1> 반복
- 반복문은 target까지 이동했다가 반복문의 어떤 조건을 만족하지 못하면 다시 원래의 자리로 돌아오는 구조이다.
- realtive offset : target~현재 위치 사이의 거리를 byte 수로 나타낸 것
- realtive offset은 EIP에 더해진다.
- backward로 돌아갈 때 = EIP 감소 / forward로 나아갈 때 = EIP 증가
2> 사용
LOOP target : [1] ECX를 1을 먼저 감소시키고 [2] 특정 조건(ECX가 0이 아니면)이면 target으로 점프한다.
- target으로 돌아가는 것이 곧 loop를 반복하는 것이다.
- ECX가 0이 되면 loop를 멈출 수 있다. (다만 맨 처음에 ECX를 감소시키니 ECX가 처음에 0인 경우 ECX 한바퀴를 돈다.)
3> 예시 1
mov ax,0
mov ecx,5
L1: add ax,cx
loop L1 ; ECX가 0이 될 때까지 L1 반복 (L1을 할 때마다 ECX는 1씩 감소한다.)
- loop L1 :
- ECX가 0이 될 때까지 L1 반복
- L1을 할 때마다 ECX는 1씩 감소한다.
- 처음에는 5(cx)를 ax에 더하고, 4(cx)를 ax에 더하고 ... 1(cx)을 ax에 더하고 그 다음에는 cx가 0이므로 loop을 멈춘다.
4> 예시 2
relative offset이 SBYTE인 경우 => 0의 뒤로는 -128까지 있고, 앞으로는 127까지 있다.
mov ax, 6
mov ecx, 4
L1:
inc ax
loop L1
- L1은 4번 시행되고
- AX=10이 된다.
5> 예시 3
mov ecx, 0
X2:
inc ax
loop X2
- (맨 처음) loop X2 : [1] ECX 1 감소 -> [2] ECX가 0인지 확인 (0이 아니다.)
- ECX는 32bit이므로 1바퀴 돌려면 4,294,967,296회 loop를 실행해야 한다.
6> 예시 4 : Nested Loop
.data
count DWORD ?
.code
mov ecx,100 ; set outer loop count
L1:
mov count,ecx ; save outer loop count
mov ecx,20 ; set inner loop count
L2:
loop L2 ; repeat the inner loop
mov ecx,count ; restore outer loop count
loop L1 ; repeat the outer loop
7> 예시 5 : Summing an Integer Array
.data
intarray WORD 100h,200h,300h,400h
.code
mov edi,OFFSET intarray ; address of intarray
mov ecx,LENGTHOF intarray ; loop counter
mov ax,0 ; zero the accumulator
L1:
add ax,[edi] ; add an integer
add edi,TYPE intarray ; point to next integer
loop L1 ; repeat until ECX = 0
8> 예시 6 : Copying a String
.data
source BYTE "This is the source string",0
target BYTE SIZEOF source DUP(0)
.code
mov esi,0 ; index register
mov ecx,SIZEOF source ; loop counter
L1:
mov al,source[esi] ; get char from source
mov target[esi],al ; store it in the target
inc esi ; move to next character
loop L1 ; repeat for entire string
'Assembly' 카테고리의 다른 글
5-2강 - Procedure 2 (Procedure) (0) | 2020.05.21 |
---|---|
5-1강 - Procedure 1 (Stack Operation) (0) | 2020.05.21 |
4-3강 - Data Transfer, Addressing and Arithmetic 3 (Data-Related Operators and Directives) (0) | 2020.05.18 |
4-2강 - Data Transfer, Addressing and Arithmetic 2 (Addition and Subtraction) (0) | 2020.05.18 |
4-1강 - Data Transfer, Addressing and Arithmetic 1 (Data Transfer Instruction) (0) | 2020.05.04 |