Link

데이터 전송 명령어

피연산자 기호
imm8: 8-bit immediate, 8비트 즉시값
imm16: 16-bit immediate, 16비트 즉시값 reg8: 8-bit register, 8비트 레지스터(A, B, C, D, E, H, L)
reg16: 16-bit register, 16비트 레지스터(BC, DE, HL, IX, IY) addr: address, 16비트 절대 주소 ($0000~$FFFF)

편의상 묵시주소지정 방식(implied addressing mode)의 명령어들은 구문 부분을 생략했다.

LD(LoaD)는 Z80의 대표적인 데이터 전송 명령어다. 통상적으로 메모리에서 레지스터로 데이터를 전송하는 작업을 적재(load)라 하고, 레지스터에서 메모리로 데이터를 전송하는 작업을 저장(store)라고 하지만, Z80 어셈블리어에서는 LD라는 단일한 니모닉으로 통합됐다. (이와 달리 6502나 대부분의 RISC 구조의 프로세서들은 저장과 적재 명령어의 니모닉이 분리되어 있다.)

이 문서에서 데이터 전송 명령어는 종류에 따라 크게 8비트 데이터 전송 명령어, 16비트 데이터 전송 명령어, (레지스터)교환 명령어, 스택 연산, 블록 전송 명령어로 분류했다.

LD 명령어는 이 중에서 8/16비트 데이터 전송 명령어에 해당하고 Z80이 다양한 레지스터를 제공하는 만큼 사용할 수 있는 피연산자의 경우의 수가 많기 때문에 본문을 시작하기 앞서 대응 가능한 피연산자들을 일람할 수 있도록 표로 정리했다.

ld N, M

열(가로)이 M, 행(세로)이 N이다.

 ABCDEHLIRIXHIXLIYHIYLBCDEHLSPIXIY(BC)(DE)(HL)(IX+d)(IY+d)imm8imm16(addr)
Axxxxxxxxxxxxx      xxxxxx x
Bxxxxxxx  xxxx      xxxxxx  
Cxxxxxxx  xxxx      xxxxxx  
Dxxxxxxx  xxxx      xxxxxx  
Exxxxxxx  xxxx      xxxxxx  
Hxxxxxxx            xxxxxx  
Lxxxxxxx            xxxxxx  
Ix                          
Rx                          
IXHxxxxx    xx             x  
IXLxxxxx    xx             x  
IYHxxxxx      xx           x  
IYLxxxxx      xx           x  
BC                         xx
DE                         xx
HL                         xx
SP               x xx      xx
IX                         xx
IY                         xx
(BC)x                          
(DE)x                          
(HL)xxxxxxx                    
(IX+d)xxxxxxx                    
(IY+d)xxxxxxx                    
(addr)x            xxxxxx        


1. 8비트 데이터 전송 명렁어

(1). 레지스터에 8비트 즉시값 전송

8비트 레지스터에 8비트 즉시값(immediate)을 쓴다. 플래그에는 아무 영향을 미치지 않는다.

LD reg8, imm8
LD IXH, imm8
LD IXL, imm8
LD IYH, imm8
LD IYL, imm8


(2). 레지스터 간 데이터 복사

8비트 레지스터에 8비트 레지스터의 값을 복사한다. 누산기 레지스터인 A 레지스터에는 특별히 인터럽트 레지스터 I와 리프레시(refresh) 레지스터 R을 복사할 수 있는데, 이 경우를 제외하면 플래그에 아무 영향을 미치지 않는다.

LD reg8, reg8


reg8에 해당하는 레지스터에서 H와 L을 제외한 레지스터들은 IXH, IXL, IYH, IYL 레지스터와 함께 피연산자로 사용될 수 있다.

LD A/B/C/D/E, IXH/IXL/IYH/IYL
LD IXH/IXL/IYH/IYL, A/B/C/D/E


LD IXH, IXH/IXL
LD IYH, IYH/IYL


상태 플래그는 I 레지스터의 값에 영향을 받는다. I 레지스터가 음수일 경우 S(Sign) 플래그는 1로 세트된다. 그렇지 않은 경우에는 0으로 리셋된다. Z(Zero) 플래그는 I가 0일 때 세트, 0이 아닐 때 리셋된다. H(Half Carry)는 리셋되며, P/V(Parity/oVerflow)는 IFF2 플립플롭의 값을 저장한다. N(Negative, Subtract)는 리셋되고, C(Carry)에는 아무 영향을 미치지 않는다. 이 명령어가 실행되고 있는 동안 인터럽트가 발생하면 패리티 플래그에는 0이 저장된다.

LD A, I


상태 플래그는 R 레지스터의 값에 영향을 받는다. R 레지스터가 음수일 경우 S(Sign) 플래그는 1로 세트된다. 그렇지 않은 경우에는 0으로 리셋된다. Z(Zero) 플래그는 R이 0일 때 세트, 0이 아닐 때 리셋된다. H(Half Carry)는 리셋되며, P/V(Parity/oVerflow)는 IFF2 플립플롭의 값을 저장한다. N(Negative, Subtract)는 리셋되고, C(Carry)에는 아무 영향을 미치지 않는다. 이 명령어가 실행되고 있는 동안 인터럽트가 발생하면 패리티 플래그에는 0이 저장된다.

LD A, R


특수 레지스터인 I와 R에 누산기 레지스터 A의 값을 복사한다. 상태 플래그에는 아무 영향을 미치지 않는다.

LD I, A
LD R, A


(3). 메모리에서 레지스터로 데이터 전송

8비트 메모리 데이터를 레지스터로 전송한다. 이를 통상적으로 적재(load)라고 한다.
Z80의 8비트 적재 명령어는 주소지정 방식에 따라 직접(direct) 또는 절대(absolute) 주소지정, 레지스터 간접 주소지정, 인덱스 주소지정 방식을 사용하는 그룹으로 분류된다.

직접 주소지정 방식(direct addressing mode)
16비트 절대 주소(absolute address)를 사용하여 피연산자의 주소를 지정한다. 이 방식을 사용하는 8비트 적재 명령어 중에서는 목적지로 지정 가능한 레지스터가 누산기 레지스터 A밖에 없다는 점에 유의해야 한다.

LD A, (addr)


레지스터 간접 주소지정 방식(register indirect addressing mode)
피연산자의 메모리 주소를 저장하고 있는 레지스터를 간접 참조하여 피연산자에 접근한다.

LD reg8, (BC)
LD reg8, (DE)
LD reg8, (HL)


인덱스 주소지정 방식(indexed addressing mode)
16비트 인덱스 레지스터 IX와 IY를 베이스 주소로 하고 부호 있는 8비트 정수(-128~+127) d를 변위displacement(또는 오프셋offset)로 하는 피연산자에 접근한다.

LD reg8, (IX+d)
LD reg8, (IY+d)


(4). 레지스터에서 메모리로 데이터 전송

8비트 레지스터의 값을 메모리로 전송한다. 이를 통상적으로 저장(store)이라고 한다.
Z80의 저장 명령어 역시 적재 명령어와 마찬가지로 주소지정 방식에 따라 직접 주소지정, 레지스터 간접 주소지정, 인덱스 주소지정 방식을 사용하는 그룹으로 분류된다.

직접 주소지정 방식

LD (addr), A


레지스터 간접 주소지정 방식

LD (BC), A
LD (DE), A
LD (HL), reg8


인덱스 주소지정 방식

LD (IX+d), reg8
LD (IY+d), reg8


2. 16비트 데이터 전송 명령어

Z80의 16비트 데이터 전송 명령어에서 사용할 수 있는 레지스터는 범용 레지스터쌍 BC, DE, HL과 인덱스 레지스터 IX와 IY, 스택 포인터 SP로 구성된다. 16비트 데이터 전송 명령어는 8비트 데이터 전송에 비해 지원하는 명령어 종류가 제한적이다. 스택 포인터를 사용하는 경우를 제외하면 16비트 레지스터 간의 데이터 복사 명령어는 존재하지 않는다. 레지스터 간접 주소를 사용하는 명령어도 없기 때문에 16비트 확장 즉시값을 사용하거나 직접 주소를 사용하여 메모리 주소를 지정해야 한다.

LD reg16, imm16
LD reg16, (addr)
LD (addr), reg16
LD SP, HL
LD SP, IX
LD SP, IY


3. 교환 명령어

EX
Exchange; 16비트 데이터 교환
EX AF, AF'를 제외하면 플래그는 그대로 유지된다. EX AF, AF' 명령어는 인터럽트 발생 시 AF 레지스터쌍을 스택에 푸시하는 방법 대신 자주 사용된다. AF’는 AF(누산기와 상태 레지스터)의 보조(또는 섀도우) 레지스터다.
EX (SP), HL/IX/IY 명령어는 레지스터 HL/IX/IY의 값을 스택에 가장 마지막으로 푸시된 값과 교환한다.

EX AF, AF'
EX DE, HL
EX (SP), HL
EX (SP), IX
EX (SP), IY


EXX
Exchange; 레지스터와 보조(섀도우) 레지스터 간의 상호 교환
플래그는 유지된다. B, C, D, E, H, L 레지스터를 B’, C’, D’, E’, H’, L’과 교환한다. 인터럽트 발생 시 레지스터를 스택에 푸시하는 대신 EXX 명령어를 사용함으로써 성능을 향상시킬 수 있다. A와 F 레지스터는 교환되지 않는다는 점에 주의해야 한다.

4. 스택 연산 명령어

Z80의 스택 연산은 16비트 데이터 전송 명령어의 일종이다. 따라서 피연산자는 전부 16비트 레지스터쌍으로 주어진다.

PUSH
Push; 16비트 레지스터 값을 스택에 푸시
플래그에는 아무 영향을 미치지 않는다.

PUSH AF
PUSH reg16


POP Pop; 스택(메모리)에 저장된 데이터를 16비트 레지스터에 적재한다.
AF를 팝 하는 경우를 제외하면 플래그에는 아무 영향을 미치지 않는다.

POP AF
POP reg16


5. 블록 전송 명령어

블록 전송 명령어는 메모리의 한 영역에서 다른 영역으로, 즉 메모리에서 메모리로 최대 64KB까지의 데이터를 블록으로 전송할 수 있는 강력한 명령어다.

블록 전송 명령어들은 다음 세 가지 레지스터쌍을 특수한 용도로 사용한다. HL을 출발지로, DE를 목적지로 사용한다고 함은 HL에는 전송할 데이터의 시작주소를, DE에는 전송된 데이터를 쓸 목적지의 시작 주소를 저장한다는 것을 가리킨다. (이는 마치 LD (DE), (HL)라는 명령어를 실행하는 것과 같다. (물론 Z80의 LD 명령어는 이런 형식의 피연산자를 지원하지 않는다.)) 명령어가 실행될 때마다 DE와 HL의 값은 자동으로 증가하거나 감소한다. BC에는 전송할 데이터의 바이트 수를 지정한다. 카운터로 사용되기 때문에 명령어 실행 후에는 자동으로 감소한다.

레지스터용도
HL출발지 주소(Source Address)
DE목적지 주소(Destination Address)
BC전송 바이트 개수

블록 전송 명령어는 LDI, LDIR, LDD, LDDR 네 가지가 존재하며, LDI와 LDD는 출발지와 목적지 주소에서 증가하는지 감소하는지에서 차이점이 있다. LDI와 LDD는 1바이트의 메모리만 전송하기 때문에 데이터 블록을 전부 전송하기 위해서는 별도의 반복 처리가 필요하다. 이런 반복을 자동으로 처리해주는 명령어가 LDIR과 LDDR이다.

LDI Load and Increment; 출발지와 목적지 주소를 증가시키면서 메모리 간 데이터 1바이트 복사
HL에는 데이터 블록의 출발지 주소를, DE에는 데이터 블록이 복사될 목적지 주소를, BC에는 데이터 블록의 바이트 크기를 지정한다. LDI를 실행하면 (HL)에 있는 1바이트 데이터가 (DE)로 복사되고 HL과 DE의 값이 1씩 자동으로 증가한다. 또한 BC는 1 감소한다. LDI를 호출하고 BC의 값이 0이 되면 오버플로우가 발생하여 P/V(패리티/오버플로우) 플래그가 0으로 리셋된다.

LDD Load and Decrement; 출발지와 목적지 주소를 감소시키면서 메모리 간 데이터 1바이트 복사
HL에는 데이터 블록의 출발지 주소를, DE에는 데이터 블록이 복사될 목적지 주소를, BC에는 데이터 블록의 바이트 크기를 지정한다. LDD를 실행하면 (HL)에 있는 1바이트 데이터가 (DE)로 복사되고 HL과 DE의 값이 1씩 자동으로 감소한다. 또한 BC는 1 감소한다. LDD를 호출하고 BC의 값이 0이 되면 오버플로우가 발생하여 P/V(패리티/오버플로우) 플래그가 0으로 리셋된다.

LDIR Load and Increment and Repeat; 출발지와 목적지 주소를 증가시키면서 BC에 지정한 바이트 수만큼 데이터 블록 복사
HL에는 데이터 블록의 출발지 주소를, DE에는 데이터 블록이 복사될 목적지 주소를, BC에는 데이터 블록의 바이트 크기를 지정한다. LDIR을 실행하면 BC가 0이 될 때까지 LDI 명령어를 반복한다. P/V 플래그는 0으로 리셋된다.

LDDR Load and Decrement and Repeat; 출발지와 목적지 주소를 감소시키면서 BC에 지정한 바이트 수만큼 데이터 블록 복사
HL에는 데이터 블록의 출발지 주소를, DE에는 데이터 블록이 복사될 목적지 주소를, BC에는 데이터 블록의 바이트 크기를 지정한다. LDDR을 실행하면 BC가 0이 될 때까지 LDD 명령어를 반복한다. P/V 플래그는 0으로 리셋된다.

참고 문헌