首页 > 代码库 > 义隆单片机学习笔记之(二) 指令系统

义隆单片机学习笔记之(二) 指令系统

指令系统

EM78156 & EM78P156 单片机共有的 58 条指令,其宽度为 13 位。(操作码+操作数)

指令周期 :取指令、分析指令、取操作数、执行

 

EM78 系列八位微控制器除一个指令需两个周期之外,其他的指令只需一个指令周期,除了对 PC (Program Counter)
做 “写”的指令,需二个指令周期,如 (MOV PC, A)。

 

EMC 汇编语言指令集
符号解说:
1.符号‘R’:代表寄存器中的一个。
2.符号‘B’:代表寄存器的某一位。
3.符号‘K’:代表 8 位或 10 位的常数。
4.符号‘A’:代表累加寄存器
5.常数之前加@
6.十六进制前加0x,十进制前不加
7.注释之前加;
8.ORG定义起始地址(伪指令)
9."==" 定义一代号值(PC == 0X02,需要在实际使用前定义)

 1 ADD A,R ;A+R->A 
 2 ADD R,A ;A+R->R 
 3 AND A,R ;A&R->A
 4 AND R,A ;A&R->R 
 5 CLR R ;0->R
 6 CLRA ;0->A
 7 COM R ;/R->R
 8 COMA R ;/R->A
 9 DAA ;A 寄存器调整为 BCD 值
10 DEC R ;R-1->R
11 DECA R ;R-1->A
12 DJZ R ;R-1->R 结果为零就跳过下一个指令 
13 DJZA R  ;R-1->A 结果为零就跳过下一个指令
14 INC R ;R+1->R
15 INCA R ;R+1->A
16 JZ R ;R+1->R,  结果为零就跳过下一个指令 
17 JZA R ;R+1->A,  结果为零就跳过下一个指令
18 MOV R,A ;A->R
19 MOV A,R ;R->A
20 MOV R,R ;R->R
21 OR A,R ;A OR R ->A
22 OR R,A ;A OR R->R
23 SUB A,R ;R-A->A
24 SUB R,A ;R-A->R 
25 XOR A,R ;A XOR R->A
26 XOR R,A ;A XOR R->R
27 BC R,B ;0->R(B)
28 BS R,B ;1->R(B)
29 JBC R,B ;如果 R(B)=0, 则跳过下一个指令
30 JBS R,B ;如果 R(B)=1, 则跳过下一个指令 
31 RLC R ;循环左移
32 RLCA R ;循环左移 累加器A
33 RRC R ;循环右移
34 RRCA R ;循环右移A
35 SWAP R ;交换    R(0-3)->R(4-7) R(4-7)->R(0-3)
36 SWAPA R ;交换A  将所选定的寄存器﹐高 4 位以及低 4 位﹐互換
37 ;以下K为常量
38 ADD A,K ;A+K->A
39 AND A,K ;A&K->A
40 CALL K ;PC+1->[SP]  ;(PAGE,K)->PC
41 CONTR ;CONT->A  读cont
42 CONTW ;A->CONT 写cont
43 DISI ;禁止中断
44 ENI ;使能中断 
45 INT ;跳转到内存中的中断向量处 PC+1->[SP] 001H->PC  
46 IOR R ;IOCR->A
47 IOW R ;A->IOCR  读写IO输入输出控制寄存器
48 JMP K ;(PAGE,K)->PC 
49 MOV A,K ;K->A
50 NOP ;No Operation
51 OR A,K ;A OR K->A
52 RET ;[堆栈顶端]->PC ;return 
53 RETI ;[堆栈顶端]->PC,使能中断  ;return 并开启中断
54 RETL K ;K->A, [堆栈顶端]->PC ;return 并返回值到A
55 SLEP ;0->WDT,振荡器停止振荡 
56 SUB A,K ;K-A->A 
57 TBL ;PC+A->PC 查找表 ;占用两个指令周期
58 WDTC ;0->WDT ; 清空看门狗计时器
59 XOR A,K ;A XOR K->A 

 

寻址方式

立即数寻址(直接从指令中获取数据)

MOV A,@0x16   ;将常数0x16送给寄存器A

直接寻址(直接给出寄存器的地址)

;例:将寄存器 0X20 的内容,COPY 到寄存器 0X21 中。 
MOV  A, 0X20 
MOV  0X21, A

间接寻址 (R4中存储的是另一个寄存器的地址)

R4 的 bit0-5 是用来选择寄存器(地址:00-06,0F-3F);方便循环寻址。

 1 ;例:写一个程序,將寄存器 0X20~0X3F 的值都填 0。 
 2 
 3 MOV  A, @0X20          ;设定A = 0X20。
 4 MOV  0X04, A           ;设定间接寻址寄存器(0X04)
 5 AGAIN:                  ;的內含值为0X20
 6 CLR  0                   ;清除0X04所指的寄存器。
 7 INC  0X04                ;递增间接寻址寄存器(0X04) 
 8 MOV  A, 0X04             ;设定A=0X04寄存器的值。
 9 XOR  A, 0X3F             ;比较间接寻址的位址是否
10 JBS  0X03, 2             ;以到0X3F。若是则结束。
11 JMP  AGAIN               ;否则在继续。
12 END:               

 位寻址
这种位寻址是对寄存器中的任一位(bit)进行操作。

BS 0x12,2   ;将寄存器0x12的第2位置为“1”。

 

例程(基本指令)

1.数据操作,(运算指令可以直接执行,数据在寄存器间的移动一定要以A为中转,立即数只能与A直接交互,数据拷贝到一般寄存器中只能通过A)

1 ;下两行指令敘述为 A = R11+ R12. 
2  MOV  A,0x11 
3  ADD  A,0x12   ;A = R11+ R12
1 ;下两行指令敘述为 R10= R11+ R12. 
2  MOV  A,0x11 
3  MOV  0x10,A 
4  MOV  A,0x12 
5  ADD  0x10,A   ;R10= R11+ R12 
1 ;下两行指令敘述为 A = 0x01 + 0x01. 
2  MOV  A,@0x01  ;A = 0x01 
3  ADD  A,@0x01  ;A = 0x02
1 ;將 port 6 和 R10register AND 起來, 并将结果输出到 port6 
2  MOV  A,0x6    ;從 port6 输入内容 
3  AND  A,0x10   ;把内容和 R10 做 AND  
4  MOV  0x6,A     ;将结果输出到 port6 
1  R10= R11AND R12
2  MOV  A,0x11 
3  MOV  0x10,A 
4  MOV  A,0x12 
5  AND  0x10,A   ;R10= R11AND R12
1 ;R10 寄存器的位 “b”被清为 0。 
2  MOV  A,@0x0f 
3  MOV  0x10,A   ;R10= 00001111 
4  BC   0x10,3   ;R10= 00000111 
;將狀态寄存器的零标志設成 1。 
 BS  0x3,2 
 1 ;CALL k
 2 ;操作內容  PC+1 --> [Top of Stack] 
 3 ;            k --> PC(9::0) 
 4 ;            R3(7::5) --> PC(12::10)
 5 HERE: 
 6           CALL SUBRTN 
 7 CONT: 
 8           MOV  A,@10 
 9 
10 ;执行 CALL 指令之前 
11 ;PC = address HERE 
12 ;执行 CALL 指令之后 
13 ;PC = address SUBRTN 
14 ;[Top of Stack] = address CONT
CLR  0x10  ;清除 0x10 寄存器
CLRA ; 清除 A 寄存器﹐同時設定 Z 标志
1 ;COM  R 
2 ;将 R 暂存, 取补数(取反)﹐再存入 R 寄存器中。 
3  MOV  A,@0x11 
4  MOV  0x10,A   ;R10= 0x11 
5  COM  0x10  ;R10= 0xEE 
1 ;COMA R
2 ;将所指定的寄存器取补数﹐再放入 A 寄存器中。 
3 ;从 port6 输入一个值﹐将其取补数之后在由 port6 输出。
4  MOV  A,0x6 
5  MOV  0x10,A 
6  COMA 0x10 
7  MOV  0x6,A 

  (减法运算,A中存放的是始终是减数!)

 1 ;SUB  A,R
 2 ;將 R 寄存器中的值减去 A 寄存器中的值﹐再存回 A 寄存器中
 3 
 4 ;SUB  R,A 
 5 ;将 R 寄存器中的值减去 A 寄存器中的值﹐再存回 R 寄存器中。
 6 
 7 ;SUB  A, k
 8 ;立即数 k 的值减去 A 寄存器中的值﹐再存回 A 寄存器中。
 9 
10 ;说明如何完成 A = 0x99-0x55 的计算式 
11  MOV  A,@0x99 
12  MOV  0x10,A   ;R10 = 0x99
13  MOV  A,@0x55 
14  SUB  A,0x10    ;A = 0x44 
15 
16 ;说明如何完成 A = 0x02 - A 的计算式 
17  MOV  A,@0x01    ;A = 0x01 
18  SUB   A,@0x02   ;A = 0x02 - 0x01 = 0x01 
19 ;C flag = 1 , 进位标志 C =  1﹐相减结果为正值。 

 

1 ;IO配置
2 ;IOR  R
3 ;将控制寄存器 IOCR中的值移到寄存器 A 中。 
4 IOR   0xf        ;取得 IOCF中的內容﹐并载入 A 中 
5 MOV  0x10,A   ;储存在寄存器 0x10 中
1 ;IOW R 
2 ;将 A 寄存器(累加器)的内容载入控制寄存器 IOCR中
3 ;将 port6 設定成输出口。 
4  MOV   A, @0 
5  IOW   0x6 

 

循环:

 1 ;DECA R
 2 ;R-1 --> A
 3 ;递减 R 寄存器的值﹐并且将结果存入 A 寄存器中。
 4 
 5 ;说明如何作一个计数 16 次的循环 
 6           STATUS  ==  3  ﹔状态寄存器 
 7           Z_FLAG  ==  2  ﹔零标志在状态暂存中是 BIT2 
 8           MOV  A,@0x10 
 9           MOV  0x10,A 
10 LOOP: 
11           DECA 0x10 
12           MOV  0x10,A 
13           JBS   STATUS,Z_FLAG 
14           JMP   LOOP 
 1 ;DEC  R
 2 ;R-1 --> R
 3 ;将所指定的 R 寄存器內含值减 1。
 4 
 5 ;说明如何作一个计数 16 次的循环 
 6          STATUS  ==  3  ; 状态寄存器 
 7          Z_FLAG  ==  2  ﹔零标志在状态暂存中是 BIT2 
 8          MOV  A,@0x10 
 9          MOV  0x10,A 
10 LOOP: 
11          DEC  0x10 
12          JBS   STATUS,Z_FLAG 
13          JMP   LOOP 

 

 1 ;DJZA R
 2 ;R - 1 --> A, skip if 0
 3 ;将所指定 R 寄存器的內含值减 1﹐并将结果存於 A 寄存器上﹔如果结果为
 4 ;0﹐则下一个指令将被跳过。 
 5 ;举例说明
 6 
 7 HERE: 
 8          DJZA   0x9 
 9 CONT: 
10          MOV  A,0x10 
11 SKIP: 
12          ADD  A,@10 
13 
14 ;在执行 DJZA 指令之前 
15 ;PC = address HERE 
16 ;在执行 DJZA 指令之后 
17 ;A=R9-1 
18 ;if A = 0, PC = address SKIP 
19 ;if A ≠0, PC = address CONT    
 1 ;DJZ  R
 2 ;R - 1 --> R, skip if 0 
 3 ;将所指定 R 寄存器的內含值减 1﹐并将结果存回 R 寄存器上﹔如果结果为
 40﹐则下一个指令将被跳过。 
 5 ;寄存器 R10递减﹐ 若结果不等于 
 6 ;0 , 执行 JMP 指令﹐若結果等于 0﹐ 
 7 ;JMP 指令不执行  
 8  
 9          MOV  A,@100 
10          MOV  0x10,A 
11 LOOP: 
12         
13          DJZ  0x10 
14        JMP LOOP

 

 1 ;INCA R
 2 ;R + 1 --> A 
 3 ;将被指定 R 寄存器的內含值加 1,并将结果储于 A 寄存器中。
 4  MOV  A,@0x11 
 5  MOV  0x10,A   ;R10= 0x11 
 6  INCA 0x10  ;A = 0x12 
 7  
 8 ;INC  R
 9 ;R + 1 --> R 
10 ;将被指定 R 寄存器的內含值加 1﹐並且将结果再存回 R 寄存器中。
11  MOV  A,@0x11 
12  MOV  0x10,A   ;R10= 0x11 
13  INC   0x10  ;R10= 0x12

跳转:(很多情况下,跳转伴随着++与--)

1 ;0x55﹐就跳到 ERROR 这支子程序。
2   STATUS  ==  3 
3   Z_FLAG  ==  2 
4   MOV  A,@0x55 
5   XOR  A,0x10 
6   JBS   STATUS,Z_FLAG 
7   JMP   ERROR 

 

 1 ;JMP  k
 2 ;k --> PC(9::0) 
 3 ;R3(7::5) --> PC(12::10)
 4 ;当执行一个跳转指令﹐指令后所描述的执行地址会载入程序计数器中。 
 5 
 6 HERE:
 7      JMP  BRANCH 
 8 ;执行 JMP 指令之前 
 9 ;PC = address HERE 
10 ;执行 JMP 指令之后 
11 ;PC = address BRANCH 

 

 1 ;JZA  R
 2 ;R+1 --> A, skip if result = 0 
 3 ;将所选定的寄存器 R 的內容加 1﹐并将结果存于 A 寄存器﹐若结果为 0﹐
 4 ;则跳过下一个指令。
 5 ;Port 6 输出递减的二进位数值。
 6 
 7      MOV  A,@0x00 
 8 LOOP: 
 9      MOV  0x6,A          ;IO6
10      MOV  0x10,A         
11      JZA  0x10 
12      JMP  LOOP 
 1 ;JZ  R 
 2 ;R+1 --> R, skip if result = 0
 3 ;将所选定的寄存器 R 的內容加 1﹐并将结果存於 R 寄存器﹐若结果为 0﹐
 4 ;则跳过下一个指令。 
 5 HERE: 
 6      JZ  0x10 
 7 CONT: 
 8      MOV  A,0x10 
 9 SKIP: 
10      ADD  A,@10 
11 ;执行 JZ 指令之前 
12 ;PC = address HERE 
13 ;执行 JZ 指令之后 
14 ;R10 = R10-1 
15 ;if R10= 0, PC = address SKIP 
16 ;if R10 ≠0, PC = address CONT

 

 1 ;JBC  R,b
 2 ;if R(b) = 0, skip 
 3 ;如果寄存器 R 的位 “b”是“0”,则跳过下一个指令。
 4 ;测试 0x10 寄存器的 bit0﹐若是为”0”则 port5 的 bit0 设成”0”﹔若
 5 ;0x10 寄存器的 bit0 为”1”﹐則 port5 的 bit0 设成”1”。
 6 
 7  JBC  0x10,0 
 8  BS  0x5,0 
 9  JBS  0x10,0 
10  BC  0x5,0 
 1 ;JBS  R,b 
 2 ;如果寄存器 R 的位 “b”是“1”,则跳过下一个指令。
 3 ;
 4 HERE JBC  0x9,3 
 5 CONT MOV  A,@10 
 6 SKIP ADD  A,0x10 
 7 ;执行 JBC 指令之前 
 8 ;PC = address HERE 
 9 ;执行 JBC 指令之后 
10 ;if R9(3) = 0, PC = address CONT 
11 ;if R9(3) ≠0, PC = address SKIP 

 

1 ;NOP
2 ;No Operation
3 ;不做任何工做﹐用来做时间的延迟。
4 ;
5 ;P50 输出 3 μs 的突波. (system clock = 2MHz) 
6  BS  0x5,0x0   ;P50 输出为 high 
7  NOP              ;延迟两个指令周期 
8  NOP 
9  BC  0x5,0x0   ;P50 输出为 low

 

 1 ;RET
 2 ;[Top of Stack] --> PC 
 3 ;从子程序中返回, 堆栈最上面的数值载入程序计数器PC
 4 ;
 5 TEST: 
 6 ?
 7 ?
 8  RET 
 9 ?
10 ?
11  CALL TEST 
12 HERE: 
13  ADD  A,@0x1 
14 ?
15 ?
16 ;在呼叫 RET 指令之前。 
17 ;堆栈的顶端 Top of Stack = address HERE 
18 ;在呼叫 RET 指令之后。 
19 ;程序计数器 PC = address HERE 
 1 ;RET L
 2 ;RETL k
 3 ;k --> A
 4 ;[Top of Stack] --> PC 
 5 ;从子程序返回﹐并将立即值载入 A 寄存器(累加器)中。
 6 ;堆栈最顶端的数值载入程序计数器中
 7 ;建立一个 7 段显示器转換表﹐並用 port6 驱动 7 段显示器。
 8 
 9 ;REGISTER DEFINE 
10 PC  ==  2 
11 TRANS: 
12  ADD  PC,A 
13  RETL 0XFC 
14  RETL 0XC0 
15  RETL 0XEA 
16  RETL 0XF2 
17  RETL 0X66 
18  RETL 0XB6 
19  RETL 0XBE 
20  RETL 0XE0 
21  RETL 0XFE 
22  RETL 0XF6 
23 MAIN: 
24 ?
25 ?
26 ?
27  MOV  A,0x10  ;将寄存器的內含值载入 A 中 
28  CALL TRANS 
29  MOV  0x6,A  ;输出到 7 段显示器 
30 ?
31 ?
32 ?

 

中断

 1 ;INT
 2 ;PC + 1 --> [Top of Stack]
 3 ;0001H --> PC 
 4 
 5 ;软件中断指令﹐首先将下一个地址存入堆栈中﹐然后将 0x01 载入程序寄
 6 ;存器中。
 7 ;执行 INT 指令之前 
 8 ;PC = address HERE 
 9 ;执行 INT 指令之后 
10 ;PC = 0001H 
11 ;[Top of Stack] = address CONT
12 
13              ORG  0x001 
14              JMP  SET_INT 
15 
16 SET_INT﹕ 
17              。。。
18              RET 
19 
20 MAIN﹕ 
21              。。。
22 
23 HERE﹕ 
24              INT 
25 CONT﹕ 
26              CLRA 

 

位操作:

 移位操作(仅仅是循环移位,连同进位位一起,移位之前根据需要可能要先处理好进位位)

   
1 ;RLCA R
2 ;将所指定的寄存器的內容﹐连同进位标志一起向左移 1 位﹐并将结果存於
3 ;A 寄存器
4 ;将指定的寄存器放向左移 1 位﹐并将结果由 port6 输出。 
5  BIT_BUF  ==  0x10 
6  RLCA BIT_BUF  
7  MOV  0x6,A 

1 ;RLC 
2 ;将所指定的寄存器的內容﹐连同进位标志向左移 1 个位原﹐结果存在原
3 ;先的寄存器。
4 RLCA 0x10 ﹔ 
5 RLC   0x10 ﹔將 0x10 寄存器的值向左移 1    
6  

 

 
 
 
1 ;RRCA R 
2 ;R(n) --> A(n-1), R(0) --> C, C --> A(7)
3 ;R 寄存器的內含值又移 1-bit﹐右移时包含 C(进位标志) ﹐如下图﹐并将
4 ;结果存于 A 寄存器。
5 ;将指定的寄存器放向右移 1 位﹐并将结果由 port6 输出: 
6  BIT_BUF  ==  0x10 
7  RRCA BIT_BUF  
8  MOV  0x6,A 
1 ;RRC
2 ;R(n) --> R(n-1), R(0) --> C, C --> R(7) 
3 ;所指定的寄存器的內容﹐连带着进位标志接向右移 1 位
4  MOV  A,@0x0f 
5  CLR  0x3,0    ;clear C flag 
6  MOV  0x10,A   ;R10= 00001111
7  RRC  0x10     ;R10= 00000111, C = 1
 
;SWAPA 
;R(3::0) --> A(7::4)
;R(7::4) --> A(3::0)
;将所选定的寄存器﹐高 4 位以及低 4 位﹐互換﹐并将结果存于 A 寄存器。
;将 port6 的內容﹐高 4 位以及低 4 位互換。 
 MOV  A,0x6 
 MOV  0x10,A 
 SWAP 0x10 
 MOV  0x6,A 
1 ;SWAP
2 ;R(3::0) <--> R(7::4)
3 ;将所选定的寄存器﹐高 4 位以及低 4 位﹐互換。
4  MOV  A,@0x43 
5  MOV  0x10,A   ;R10 = 0x43 
6  SWAP 0x10  ;R10 = 0x34 

逻辑操作:

 1 ;XOR  A,R 
 2 ;将A 寄存器的值和R 寄存器的值XOR 在一起﹐并且将结果存入A 寄存器中
 3 ;XOR  R,A 
 4 ;将A 寄存器的值和R 寄存器的值XOR 在一起﹐并且将结果存入R 寄存器中。
 5 ;XOR  A, k 
 6 ;
 7 ;测试 0x10 寄存器內含值是否为 0x55﹐如果 0x10 寄存器的內含值不为
 8 ;0x55﹐就跳到 ERROR 这支子程序。
 9  STATUS  ==  3 
10  Z_FLAG  ==  2 
11  MOV  A,@0x55 
12  XOR  A,0x10 
13  JBS   STATUS,Z_FLAG 
14  JMP   ERROR 
15 
16 ;下面的指令敘述﹐完成 R10= R11XOR R12
17  MOV  A,0x11 
18  MOV  0x10,A 
19  MOV  A,0x12 
20  XOR  0x10,A    ;R10= R11XOR R12
21 
22 ;下面的指令敘述﹐完成 A = A XOR 0xF0.
23  MOV  A,@0x00   ;A = 0x00 
24  XOR  A,@0xF0   ;A = 0xF0