标题：单片机汇编指令
简介
  单片机汇编指令现在单片机的编程大多 是C语言完成 
但有时代码中必须嵌入汇编语言解决某些特定的问题
对于程序调试 汇编语言更是不可或缺。
直接使用汇编指令编写单片机程序，对硬件的控制更加直接，可以直接操作物理地址，寄存器，端口等；其它更高级的语言（如：C语言）对硬件的控制是依赖于类库来实现的。并且，对于一些对程序大小和运行速度有非常严苛要求的项目而言，都必须使用汇编指令。C语言只是为了方便编写，与机器打交道的其实都是2进制得代码，汇编语言就是这些代码好记忆的名称和规则，只是比C语言难理解些。
单片机的组成
单片机要自动完成计算，它应该具有哪些最重要的部分呢？
我们以打算盘为例计算一道算术题。例：36+163×156－166÷34。现在要进行运算，首先需要一把算盘，其次是纸和笔。我们把要计算的问题记录下来，然后第一步先算163×156，把它与36相加的结果记在纸上，然后计算166÷34，再把它从上一次结果中减去，就得到最后的结果。
现在，我们用单片机来完成上述过程，显然，它首先要有代替算盘进行运算的部件，这就是“运算器”；其次，要有能起到纸和笔作用的器件，即能记忆原始题目、原始数据和中间结果，还要记住使单片机能自动进行运算而编制的各种命令。这类器件就称为“存贮器”。此外，还需要有能代替人作用的控制器，它能根据事先给定的命令发出各种控制信号，使整个计算过程能一步步地进行。但是光有这三部分还不够，原始的数据与命令要输入，计算的结果要输出，都需要按先后顺序进行，有时还需等待。
如上例中，当在计算163×156时，数字36就不能同时进入运算器。因此就需要在单片机上设置按控制器的命令进行动作的“门”，当运算器需要时，就让新数据进入。或者，当运算器得到最后结果时，再将此结果输出，而中间结果不能随便“溜出”单片机。这种对输入、输出数据进行一定管理的“门”电路在单片机中称为“口”（Port）。在单片机中，基本上有三类信息在流动，一类是数据，即各种原始数据（如上例中的36、163等）、中间结果（如166÷34所得的商4、余数30等）、程序（命令的集合）等。这样要由外部设备通过“口”进入单片机，再存放在存贮器中，在运算处理过程中，数据从存贮器读入运算器进行运算，运算的中间结果要存入存贮器中，或最后由运算器经“出入口”输出。
用户要单片机执行的各种命令（程序）也以数据的形式由存贮器送入控制器，由控制器解读（译码）后变为各种控制信号，以便执行如加、减、乘、除等功能的各种命令。所以，这一类信息就称为控制命令，即由控制器去控制运算器一步步地进行运算和处理，又控制存贮器的读（取出数据）和写（存入数据）等。第三类信息是地址信息，其作用是告诉运算器和控制器在何处去取命令取数据，将结果存放到什么地方，通过哪个口输入和输出信息等。
存贮器又分为只读存贮器和读写存贮器两种，前者存放调试好的固定程序和常数，后者存放一些随时有可能变动的数据。顾名思义，只读存贮器一旦将数据存入，就只能读出，不能更改（EPROM、E2PROM等类型的ROM可通过一定的方法来更改、写入数据——编者注）。而读写存贮器可随时存入或读出数据。
实际上，人们往往把运算器和控制器合并称为中央处理单元——CPU。单片机除了进行运算外，还要完成控制功能。所以离不开计数和定时。因此，在单片机中就设置有定时器兼计数器，其基本结构与本连载之（二）中的举例类似。到这里为止，我们已经知道了单片机的基本组成，即单片机是由中央处理器（即CPU中的运算器和控制器）、只读存贮器（通常表示为ROM）、读写存贮器（又称随机存贮器通常表示为RAM）、输入/输出口（又分为并行口和串行口，表示为I/O口）等等组成。实际上单片机里面还有一个时钟电路，使单片机在进行运算和控制时，都能有节奏地进行。另外，还有所谓的“中断系统”，这个系统有“传达室”的作用，当单片机控制对象的参数到达某个需要加以干预的状态时，就可经此“传达室”通报给CPU，使CPU根据外部事态的轻重缓急来采取适当的应付措施。
现在，我们已经知道了单片机的组成，余下的问题是如何将它们的各部分连接成相互关联的整体呢？实际上，单片机内部有一条将它们连接起来的“纽带”，即所谓的“内部总线”。此总线有如大城市的“干道”，而CPU、ROM、RAM、I/O口、中断系统等就分布在此“总线”的两旁，并和它连通。从而，一切指令、数据都可经内部总线传送，有如大城市内各种物品的传送都经过干道进行。
单片机指令系统与汇编语言程序
前面已经讲述了单片机的几个主要组成部分，这些部分构成了单片机的硬件。所谓硬件（Hardware），就是看得到，摸得到的实体。但是，光有这样的硬件，还只是有了实现计算和控制功能的可能性。单片机要真正地能进行计算和控制，还必须有软件（Software）的配合。软件主要指的是各种程序。只有将各种正确的程序“灌入”（存入）单片机，它才能有效地工作。单片机所以能自动地进行运算和控制，正是由于人把实现计算和控制的步骤一步步地用命令的形式，即一条条指令（Instruction）预先存入到存贮器中，单片机在CPU的控制下，将指令一条条地取出来，并加以翻译和执行。就以两个数相加这一简单的运算来说，当需要运算的数已存入存贮器后，还需要进行以下几步：
第一步：把第一个数从它的存贮单元（Location）中取出来，送至运算器。
第二步：把第二个数从它所在的存贮单元中取出来，送至运算器； 第三步：相加； 第四步：把相加完的结果，送至存贮器中指定的单元。
所有这些取数、送数、相加、存数等等都是一种操作（Operation），我们把要求计算机执行的各种操作用命令的形式写下来，这就是指令。但是怎样才能辨别和执行这些操作呢？这是在设计单片机时由设计人员赋予它的指令系统所决定的。一条指令，对应着一种基本操作；单片机所能执行的全部指令，就是该单片机的指令系统（Iustruction Set），不同种类的单片机，其指令系统亦不同。
使用单片机时，事先应当把要解决的问题编成一系列指令。这些指令必须是选定的单片机能识别和执行的指令。单片机用户为解决自己的问题所编的指令程序，称为源程序（Source Program）。指令通常分为操作码（Opcode）和操作数（Operand）两大部分。操作码表示计算机执行什么操作，即指令的功能；操作数表示参加操作的数或操作数所在的地址（即操作数所存放的地方编号）。因为单片机是一种可编程器件，只“认得”二进码（0、1）。要单片机运作，单片机系统中的所有指令，都必须以二进制编码的形式来表示。例如，在Intel公司的MCS－51系列单片机中，从存贮器中取出一数到CPU中的累加器（在运算器中，参与运算、存放运算结果的专用寄存器）的指令代码为74H，累加器内容加立即数的代码为24H，再加上立即数代码，累加器送数到内部RAM存贮器的代码为F6H～F7H等。这些指令是用十六进制表示二进制的机器码。
MCS－51单片机的字长为8位，有时，要完成某些操作用一个字节尚不能充分表达。所以，在指令系统中有单字节指令，也有多字节指令。机器码是由一连串的0和1组成，没有明显的特征，不好记忆，不易理解，易出错。所以，直接用它来编写程序十分困难。因而，人们就用一些助记符（Mue monic）——通常是指令功能的英文缩写来代替操作码，如MCS－51中数的传送常用MOV（Move的缩写）、加法用Add(Addition的缩写）来作为助记符。这样，每条指令有明显的动作特征，易于记忆和理解，也不容易出错。用助记符来编写的程序称为汇编语言程序。但是，助记符编写的程序便于人理解，可单片机却只认识二进制机器代码，因此，为了让单片机能“读懂”汇编语言程序必须再转换成由二进制机器码构成的程序，这种转换过程，就称为“汇编”。汇编可借助于人工查表法来实现，也可借助PC机通过所谓“交叉汇编程序”来完成。由机器码构成的用户程序一旦“进入”了单片机，再“启动”单片机，就可让它执行输入程序所规定的任务。
汇编指令
常用单片机汇编指令：1 .MOV A,Rn 寄存器内容送入累加器 
2 .MOV A,direct 直接地址单元中的数据送入累加器 
3 .MOV A,@Ri (i=0,1)间接RAM 中的数据送入累加器 
4 .MOV A,#data 立即数送入累加器 
5 .MOV Rn,A 累加器内容送入寄存器 
6 .MOV Rn,direct 直接地址单元中的数据送入寄存器 
7 .MOV Rn,#data 立即数送入寄存器 
8 .MOV direct,A 累加器内容送入直接地址单元 
9 .MOV direct,Rn 寄存器内容送入直接地址单元 
10. MOV direct,direct 直接地址单元中的数据送入另一个直接地址单元 
11 .MOV direct,@Ri (i=0,1)间接RAM 中的数据送入直接地址单元 
12 MOV direct,#data 立即数送入直接地址单元 
13 .MOV @Ri,A (i=0,1)累加器内容送间接RAM 单元 
14 .MOV @Ri,direct (i=0,1)直接地址单元数据送入间接RAM 单元 
15 .MOV @Ri,#data (i=0,1)立即数送入间接RAM 单元 
16 .MOV DPTR,#data16 16 位立即数送入地址寄存器
17 .MOVC A,@A+DPTR 以DPTR为基地址变址寻址单元中的数据送入累加器 
18 .MOVC A,@A+PC 以PC 为基地址变址寻址单元中的数据送入累加器 
19 .MOVX A,@Ri (i=0,1)外部RAM（8 位地址）送入累加器 
20 .MOVX A,@DPTR 外部RAM（16 位地址）送入累加器 
21 .MOVX @Ri,A (i=0,1)累计器送外部RAM（8 位地址） 
22 .MOVX @DPTR,A 累计器送外部RAM（16 位地址）
23 .PUSH direct 直接地址单元中的数据压入堆栈 
24 .POP direct 弹栈送直接地址单元 
25 .XCH A,Rn 寄存器与累加器交换 
26 .XCH A,direct 直接地址单元与累加器交换 
27 .XCH A,@Ri (i=0,1)间接RAM 与累加器交换 
28 .XCHD A,@Ri (i=0,1)间接RAM 的低半字节与累加器交换算术操作类指令：1. ADD A,Rn 寄存器内容加到累加器 
2 .ADD A,direct 直接地址单元的内容加到累加器 
3 A.DD A,@Ri (i=0,1)间接ROM 的内容加到累加器 
4 .ADD A,#data 立即数加到累加器 
5 .ADDC A,Rn 寄存器内容带进位加到累加器 
6 .ADDC A,direct 直接地址单元的内容带进位加到累加器 
7 .ADDC A,@Ri(i=0,1) 间接ROM 的内容带进位加到累加器 
8 .ADDC A,#data 立即数带进位加到累加器 
9 .SUBB A,Rn 累加器带借位减寄存器内容 
10. SUBB A,direct 累加器带借位减直接地址单元的内容 
11 .SUBB A,@Ri (i=0,1)累加器带借位减间接RAM 中的内容 
12 .SUBB A,#data 累加器带借位减立即数 
13 .INC A 累加器加1 
14 .INC Rn 寄存器加1 
15 .INC direct 直接地址单元加1 
16 .INC @Ri (i=0,1)间接RAM 单元加1 
17 .DEC A 累加器减1 
18 .DEC Rn 寄存器减1 
19 .DEC direct 直接地址单元减1 
20 .DEC @Rj 间接RAM 单元减 1 
21 .INC DPTR 地址寄存器DPTR 加 1 
22 .MUL AB A 乘以B，结果放在A 
23 .DIV AB A 除以B，结果放在A 
24. DA A 累加器十进制调整布尔变量操作类指令：1. CLR C 清进位位 
2 .CLR bit 清直接地址位
3 .SETB C 置进位位 
4 .SETB bit 置直接地址位 
5 .CPL C 进位位求反 
6 .CPL bit 置直接地址位求反
7 .ANL C,bit 进位位和直接地址位相“与” 
8 .ANL C,/bit 进位位和直接地址位的反码相“与”
9 .ORL C,bit 进位位和直接地址位相“或” 
10. ORL C,/bit 进位位和直接地址位的反码相“或”
11 .MOV C,bit 直接地址位送入进位位 
12 .MOV bit,C 进位位送入直接地址位 
13 .JC rel 进位位为1 则转移 
14 .JNC rel 进位位为0 则转移
15 .JB bit,rel 直接地址位为1 则转移 
16 .JNB bit,rel 直接地址位为0 则转移
17 .JBC bit,rel 直接地址位为1 则转移，该位清零逻辑操作数指令：1. ANL A,Rn 累加器与寄存器相“与” 
2 .ANL A,direct 累加器与直接地址单元相“与” 
3 .ANL A,@Ri 累加器与间接RAM 单元相“与” 
4 .ANL A,#data 累加器与立即数相“与” 
5 .ANL direct,A 直接地址单元与累加器相“与” 
6 .ANL direct,#data 直接地址单元与立即数相“与”
7 .ORL A,Rn 累加器与寄存器相“或” 
8 .ORL A,direct 累加器与直接地址单元相“或” 
9 .ORL A,@Ri 累加器与间接RAM 单元单元相“或” 
10. ORL A,#data 累加器与立即数相“或” 
11. ORL direct,A 直接地址单元与累加器相“或” 
12 .ORL direct,#data 直接地址单元与立即数相“或” 
13 .XRL A,Rn 累加器与寄存器相“异或” 
14 .XRL A,direct 累加器与直接地址单元相“异或” 
15 .XRL A,@Ri 累加器与间接RAM 单元单元相“异或” 
16 .XRL A,#data 累加器与立即数相“异或” 
17 .XRL direct,A 直接地址单元与累加器相“异或” 
18 .XRL direct,#data 直接地址单元与立即数相“异或”
19 .CLR A 累加器清“0” 
20 .CPL A 累加器求反 
21 .RL A 累加器循环左移 
22 .RLC A 累加器带进位位循环左移 
23 .RR A 累加器循环右移 
24 .RRC A 累加器带进位位循环右移 
25 .SWAP A 累加器半字节交换控制转移类指令1. ACALL addr11 绝对（短）调用子程序 
2 .LCALL addr16 长调用子程序 
3 .RET 子程序返回 
4 .RETI 中断返回 
5 .AJMP addr11 绝对（短）转移 
6 .LJMP addr16 长转移 
7 .SJMP rel 相对转移 
8 .JMP @A+DPTR 相对于DPTR 的间接转移 
9. JZ rel 累加器为零转移 
10. JNZ rel 累加器非零转移 
11. CJNE A,direct,rel 累加器与直接地址单元比较，不相等则转移 
12 .CJNE A,#data,rel 累加器与立即数比较，不相等则转移 
13 .CJNE Rn,#data,rel 寄存器与立即数比较，不相等则转移 
14 .CJNE @Ri,#data,rel 间接RAM 单元与立即数比较，不相等则转移 
15 .DJNZ Rn,rel 寄存器减1，非零转移 
16 .DJNZ direct,erl 直接地址单元减1，非零转移 
17 .NOP 空操作