II. 196 Assember
II-II. 본격적인 196 어셈블리어
지난 시간에 언급한대로 196 어셈블리어의 명령을 기능에 따라 몇가지로 분류해보면 다음과 같다.
① 데이터 전송 명령 : 데이터의 이동에 관한 명령
② 산술 연산 명령 : 산술 연산(addition, subtraction, multiplication, division)에 관한 명령
③ 논리 연산 및 shift 명령 : 논리 연산과 shift 명령
④ branch 명령 : 일반 분기(jump) 및 비교(compare), 조건 분기에 관한 명령
⑤ Stack과 subroutine 및 system 제어 명령 : subroutine call, return, stack 제어, system 제어 명령
II-II-1. 데이터 전송 명령
데이터 전송 명령은 전송하는 데이터의 크기에 따라 byte, word, double word 전송 명령 등으로 분류될 수 있다. 또한 번지 지정 방식(addressing mode)에 따라 register direct addressing mode, immediate addressing mode, indirect addressing mode, indirect addressing mode with auto increment 등으로 나눌 수 있는데, 이는 데이터 전송에서 뿐 아니라 뒤의 명령들에서도 사용되므로 정확히 알아두어야 한다.
어셈블리어의 한 문장의 형식은 이미 언급했지만, 다음과 같다.
<mnemonic> <제 1 operand>, <제 2 operand>, <제 3 operand>
ex) LDB 0F0H, 30H
데이터 전송 명령에서는 제 1 operand와 제 2 operand만을 사용한다.
데이터 전송 명령은 모두 다음과 같다.
mnemonic |
byte |
state |
기계어 |
flagS |
||
76543210 |
2 operand |
1 operand |
||||
LD |
2+BEA |
4+CEA |
101000aa |
waop |
wreg |
Z N C V VT ST |
LDB |
2+BEA |
4+CEA |
101100aa |
boap |
breg |
|
ST |
2+BEA |
4+CEA |
110000aa |
waop |
wreg |
|
STB |
2+BEA |
4+CEA |
110001aa |
baop |
breg |
|
XCH |
3 |
5+CEA |
00000100 |
waop |
wreg |
|
XCHB |
3 |
5+CEA |
00010100 |
baop |
breg |
|
LDBSE |
2+BEA |
4+CEA |
101111aa |
waop |
wreg |
|
LDBZE |
2+BEA |
4+CEA |
101011aa |
baop |
breg |
|
BMOVI |
3 |
7+8/word |
11001101 |
waop |
lreg |
① aa의 의미 ② operand의 의미
aa |
addressing mode |
00 |
register direct |
01 |
immediate |
10 |
indirect |
11 |
indexed |
wreg |
register file의 word register |
waop |
addressing mode에서 지정되는 word operand |
breg |
register file의 byte register |
baop |
addressing mode에서 지정되는 byte operand |
lreg |
register file의 long register |
BEA |
addressing mode에서 필요한 byte |
CEA |
addressing mode에서 필요한 state |
* breg, wreg, lreg를 사용하는 경우 boap는 관계없지만, wreg는 짝수, lreg는 4의 배수의 address가 되어야만 한다. |
: |
06H |
|
05H |
|
04H |
|
03H |
|
02H |
|
01H |
|
00H |
위의 table에서 LD(Load Data) 제 2 operand의 내용을 제 1 operand 의 내용으로 복사하는 명령이다. 뒤에 붙은 B는 byte를 의미한다. ST(STore)는 반대 방향으로의 데이터 전송 명령이다. 나머지는 뒤에서 언급하기로 하고, 여기서 이 명령에 대해서 간단히 알아보고 번지 지정 방법(addressing mode)에 대해서 알아보도록 하자.
II-II-1-1 data 전송 명령 형식
(1) Byte 전송 명령 형식 I
LDB <제 1 operand>, <제 2 operand>
① 제 1 operand는 byte register, 제 2 operand는 byte register 또는 번지 지정에 의해서 지정되는 memory이다.
② 결과가 저장되는 제 1 operand는 반드시 80196KC의 register file이어야 한다.
(2) Byte 전송 명령 형식 II
STB <제 1 operand>, <제 2 operand>
① 제 1 operand는 byte register, 제 2 operand는 byte register 혹은 번지 지정에 의해 지정되는 memory이다.
② STB역시 제 1 operand는 반드시 register file이어야 한다.
(3) Word 전송 명령 형식 I
LD <제 1 operand>, <제 2 operand>
① 제 1 operand는 word register, 제 2 operand는 word register 혹은 번지 지정에 의해 지정되는 memory이다.
② 역시 제 1 operand는 register file이어야 한다.
(4) Word 전송 명령 형식 II
ST <제 1 operand>, <제 2 operand>
① 제 1 operand는 word register, 제 2 operand는 word register 혹은 번지 지정에 의해 지정되는 memory이다.
② 제 1 operand는 register file이어야 한다.
위에서 볼 수 있듯이 196은 다른 CPU와는 달리 데이터 전송에서 제 1 operand가 register file 내의 어떤 memory라도 상관없다. 보통의 CPU에서는 외부 memory를 access하기 위해서는 특정한 register를 사용하거나 accumulator사용해야 한다. 이는 196의 RALU의 강점이라 할 수 있을 것이다. 이제 부터는 196의 번지 지정 방법에 대해 알아보자.
II-II-1-2 번지 지정 방법(addressing mode)
(1) 레지스터 직접 번지 지정(register direct addressing mode)
register와 register 간의 data를 직접 access할 때 사용된다.
ex) LDB 50H, 60H ; 60H byte register의 내용을 50H byte register로 전송한다.
LDB 41H, 0E0H ; 0E0H byte register의 내용을 41H byte register로 전송한다.
STB 77H, 88H ; 77H byte register의 내용을 88H byte register로 전송한다.
LD 50H, 64H ; 64H word regiser의 내용을 50H word register로 전송한다.
ST 0A0H,86H ; 0A0H word register의 내용을 86H word register로 전송한다.
note
위에서 말했던 것처럼 word 전송의 경우, operand는 반드시 word register의 address가 되어야 한다. 즉, 짝수 번지만이 사용될 수 있다. 다음과 같은 경우는 error가 된다.
LD 51H, 60H
ST 6AH, 7FH
그러나 byte 전송의 경우에는 어떤 address라도 상관이 없다.
(2) immediate 번지 지정
명령어에 저장될 data가 직접 포함되어 있는 경우의 addressing 방법으로 register에 원하는 data를 넣고 싶을 때에 사용할 수 있다. 여기에 사용되는 data의 앞에는 #을 사용해서 address(variable name)와 구분한다.
ex) LDB 81H, #50H ; byte register 81H에 data 50H가 저장된다.
LD 4AH, #1024 ; word register 4AH에 십진수 1024가 저장된다.
LDB 0BBH, #'a' ; byte register 0BBH에 'a'의 ASCII code 값이 저장된다.
note 1
데이터가 word register에 저장되는 순서는 하위, 상위의 순서로 저장된다. 예를 들어 다음 명령이 실행된 후의 memory(register file)의 내용을 보면 아래와 같다.
LD 50H, #1234H
( 명령 실행 전 )
52H |
: |
|
51H |
?? |
상위 byte |
50H |
?? |
하위 byte |
4FH |
: |
; word register 50H에 data 1234H를 저장한다.
( 명령 실행 후 )
52H |
: |
|
51H |
12H |
상위 byte |
50H |
34H |
하위 byte |
4FH |
: |
note 2
immediate addressing mode에는 STB, ST는 없다. 따라서 다음 명령의 경우는 error가 된다.
STB #14, 50H
(3) 간접 번지 지정(indirect addressing mode)
간접 번지 지정의 경우에는 register를 pointer로서 사용한다. 즉, register의 값이 실제 사용될 memory의 address가 된다. 이 경우 [ ]를 이용하여 pointer로 사용되고 있음을 나타낸다. [ ]안의 register는 반드시 word register가 되어야 한다(따라서 짝수 address register가 되어야 한다.). 0000H~0FFFFH까지의 memory 영역을 access 하기 위한 주소로 사용되기 때문이다.
ex) LDB 53H, [60H]
( 명령 실행 전 )
|
|
; word register 60H가 가리키는 memory의 내용을 byte register 53H
; 에 저장한다.
( 명령 실행 후 )
|
|
LD 60H, [70H]
( 명령 실행 전 )
|
|
word register 70H가 가리키는 memory의 내용을 word register
; 60H에 저장한다.
( 명령 실행 후 )
|
|
STB 53H, [80H] ; byte register 53H의 내용을 word register 80H가 가리키는 memory
; 에 저장한다.
ST 54H, [90H]
( 명령 실행 전 )
|
|
; word register 54H의 내용을 word register 90H가 가리키는
; memory에 저장한다.
( 명령 실행 후 )
|
|
note 1
앞서 설명했지만, [ ] 안의 register는 반드시 word address register가 되어야 한다. 즉, 짝수 address가 되어야 한다. 다음과 같은 명령은 error다.
LD 50H, [51H]
STB 59H, [5BH]
note 2
간접 번지 지정을 제 1 operand에 사용할 수 없다. 제 1 operand는 반드시 register file내의 address만 사용될 수 있다. 다음과 같은 경우는 error이다.
LDB [50H], 70H
ST [4EH], 54H
(4) 자동 증가(auto increment)가 있는 간접 번지 지정
이 경우는 간접 번지 지정과 비슷하다. 그런데, 명령 실행 후 간접 번지 지정에 사용한 register값을 byte의 경우 +1, word의 경우 +2만큼 증가시킨다. 이는 간접 번지 지정과 increment 를 혼합해 놓은 것으로, 특정 연산을 할 때 편리하게 사용할 수 있다. (ex. search, block copy, block fill...) 간접 번지 지정에서 사용한 [ ]뒤에 +를 붙여서 [ ]+로 나타낸다.
ex) LD 72H, [62H]+
( 명령 실행 전 )
|
|
; 62H가 가리키는 memory의 내용을 72H로 전송한 후(word) 62H의
; 값을 +2만큼 증가시킨다.
( 명령 실행 후 )
|
|
LDB 77H, [62H]+ ; 62H가 가리키는 memory의 내용을 77H로 전송한 후(byte) 62H의
; 값을 +1 만큼 증가시킨다.
ST 88H, [90H]+ ; 88H의 내용을(word) 90H가 가리키는 memory로 전송한 후 90H의
; 값을 +2 만큼 증가시킨다.
STB 31H, [60H]+
( 명령 실행 전 )
|
|
; 31H의 내용을(byte) 60H가 가리키는 memory로 전송한 후 60H의
; 값을 +1 만큼 증가시킨다.
( 명령 실행 후 )
|
|
자동 증가를 사용하면 inc 명령을 쓰지 않아도 되므로 프로그램을 간단하게 작성할 수 있다. 예를 들어 메모리 8000H~9000H 번지를 11H 모두 채우고 싶다면 다음과 같이 간단히 프로그램하면 된다.
LD 60H, #8000H
LDB 50H, #11H
LOOP: STB 50H, [60H]+
CMP 60H, #9000H
JNE LOOP
END