第4章 汇编语言程序设计
<p>第4章 汇编语言程序设计</p><h2 id="汇编语言语句格式">汇编语言语句格式</h2>
<h3 id="一指令格式">一、指令格式</h3>
<pre><code>[标号:]助记符 操作数1,操作数2 [;注释]
</code></pre>
<ul>
<li>标号:由1-8个字符组成,且第一个字符必须是字母。用于指示指令的地址。</li>
<li>操作数:可使用二(B结尾)、十(D结尾或省略)、十六(H结尾)进制数和字符串(加" ")</li>
<li>注释:为不可执行部分,对程序加以说明。</li>
</ul>
<h3 id="二伪指令格式">二、伪指令格式</h3>
<p>伪指令是不可执行的指令,其功能是为汇编程序提供信息。常用伪指令有:</p>
<ol>
<li>
<p>汇编起始地址命令:ORG<br>
格式: <code>ORG 地址</code><br>
功能:规定程序的起始地址,省略时起始地址从0000H开始。</p>
</li>
<li>
<p>汇编终止命令:END<br>
格式: <code>END 表达式</code><br>
功能:源程序汇编终止。在主程序模块中含有"表达式"给出程序的起始地址,在其它模块(子程序)中表达式可省略。</p>
</li>
<li>
<p>赋值命令:EQU<br>
格式:<code>字符名称 EQU 表达式</code><br>
功能:将表达式的值赋给字符名称。表达式可以是常数、地址、标号和表达式。赋值之后的字符名称可以在程序中使用。</p>
<p>例如:</p>
<pre><code>A1 EQU 20H
B1 EQU A1
C1 EQU 40H+10H
.
.
.
MOV A,# A1
BAC: ADD A,C1
</code></pre>
</li>
<li>
<p>定义数据命令:DB、DW<br>
格式:<code>[标号:] DB 字节数据项表</code><br>
功能:从指定地址(即标号)开始,在程序存储器中定义字节数据。</p>
<p>格式: <code>[标号:] DW 字数据项</code><br>
功能:从指定地址(即标号)开始,在程序存储器中定义16位字数据。高8位数据在低地址单元,低8位数据在高地址单元。</p>
<p>例如:</p>
<pre><code>ORG 1000H
TAB1: DB 1BH,'A',-2,128
TAB2: DW 302AH,34H
</code></pre>
<p>存储格式如图:</p>
<pre><code> 低 高
TAB11BH
41H
FEH
80H
TAB230H
2AH
00H
34H
</code></pre>
</li>
<li>
<p>定义存储区命令:DS<br>
格式: <code>[标号:]DS 表达式</code><br>
功能:从指定地址(即标号)开始,保留指定数目(表达式的值)的字节单元作为存储区,供程序运行使用(用于程序存储器)。</p>
<p>例如:</p>
<pre><code>ORG2000H
TAB: DS 05H
</code></pre>
</li>
<li>
<p>位定义命令:BIT<br>
格式:<code>字符名称BIT 位地址</code><br>
功能:将位地址赋给字符名称。位地址为绝对地址或符号地址。</p>
<p>例如:</p>
<pre><code>HULEDBITP1.0
</code></pre>
</li>
</ol>
<h2 id="分支程序设计">分支程序设计</h2>
<p>分支程序是根据给出的条件满足与否执行不同的走向,基本结构分为单分支、双分支和多分支程序。</p>
<ol>
<li>
<p>单分支结构<br>
给出的条件满足,则执行程序段 A,然后执行该指令下面的指令;若条件满不足,则不执行程序段 A,而是执行该指令下面的指令。</p>
</li>
<li>
<p>双分支结构<br>
给出的条件满足,则执行程序段 A,否则执行程序段 B。</p>
</li>
<li>
<p>多分支结构<br>
首先将分支按号进行排列,然后按序号的值来实现多分支选择。</p>
</li>
</ol>
<h2 id="循环程序设计">循环程序设计</h2>
<h3 id="一循环程序的基本结构">一、循环程序的基本结构</h3>
<p>在基本设计中,控制一部分指令重复执行若干次,用简短的程序完成大量的处理任务,这种按某种控制规律重复执行的程序,称为循环程序。</p>
<ol>
<li>
<p>先执行后判断结构<br>
特点是一进入循环先执行循环处理部分,然后根据循环控制条件判断是否结束循环,若不结束,则继续执行循环操作;若结束,退出循环。</p>
</li>
<li>
<p>先判断后执行结构<br>
特点是一进入循环先判断循环控制条件是否结束循环,若结束,退出循环,否则继续执行循环操作。</p>
</li>
</ol>
<p>循环程序由以下四个基本组成部分:</p>
<ol>
<li>置循环初值。设置循环开始的初始值,为循环做准备。如设计数器,工作单元初值。</li>
<li>循环处理。循环程序中重复执行的内容。</li>
<li>循环修改。修改循环参数,为执行下一次循环做准备。</li>
<li>循环控制。判断是否结束循环。</li>
</ol>
<h3 id="二循环程序设计举例">二、循环程序设计举例</h3>
<p>通常采用"计数法"来控制循环,选择"先执行,后判断"循环结构。</p>
<p>例:多个单字节数求和<br>
设:10 个字节的无符号数据依次存放在内部 RAM 40H开始的单元中,所求结果存放在 R3、R2中。本例循环次数已知,采用计数法控制循环。</p>
<p>源程序如下:</p>
<pre><code>ORG 8000H
MOV R0,#40H;置数据指针
MOV R7,#10 ;置计数器初值
MOV R3,#0 ;结果单元清零
MOV R2,#0 ;
LOOP1: MOV A,R2 ;取加数
ADD A,@R0;求和
MOV R2,A ;存结果低 8 位
JNC LOOP2 ;无进位,转LOOP2
INC R3 ;有进位,结果高 8 位加1
LOOP2: INC R0 ;修改指针
DJNZ R7,LOOP1 ;未完,继续
END
</code></pre>
<p>设计20ms延时程序<br>
延时程序与MCS-51指令执行时间有很大的关系。在使用12MHz晶振时,一个机器周期为lμS,执行一个条"DJNZ"指令的时间为2μS,<br>
20ms = 2μS×10000,<br>
由于8位的计数值最大为256,这时可用双重循环方法<br>
20ms = 2μS×100×100,</p>
<p>延时20ms程序如下的:</p>
<pre><code>D20MS:MOV R4,#100 ;20ms=2μS×100×100
; 外循环初值=100
DY1:MOV R3,#100 ;内循环初值=100
DY2:DJNZ R3,DY2 ;100×2=200=0.2ms
DJNZ R4,DY1 ;0.2×100=20ms
RET
</code></pre>
<h2 id="子程序设计">子程序设计</h2>
<p>子程序的主要特点是:在执行过程中需要由其它程序来调用,执行完毕又需要把执行流程返回到调用该子程序的程序中。</p>
<p>在子程序调用过程中须解决以下两个方面的问题:</p>
<ul>
<li>程序之间的调用与返回;</li>
<li>调用程序与被调用程序之间的参数传送。</li>
</ul>
<h2 id="程序设计举例">程序设计举例</h2>
<h3 id="查表程序">查表程序</h3>
<p>在很多情况下,通过查表程序可以简化计算,简化程序的多分支结构,提高程序的运行效率。查表所使用的数据表格是按一定顺序排列的常数,存放在程序存储器中。</p>
<p>MCS-5l指令系统用于查表的指令有两条:</p>
<pre><code>MOVC A,@A+DPTR
MOVC A,@A+PC
</code></pre>
<h3 id="布尔处理程序">布尔处理程序</h3>
<p>MCS-5l微处理器的一个最大特点就是它有很强的布尔处理能力,即对布尔变量(位变量)的处理能力,所以它最擅长开关量控制。</p>
<p>大部分硬件设计都是用组合逻辑实现复杂功能的。虽然所用硬件各式各样,但目的只有一个,那就是解若干布尔变量的逻辑函数所代表的问题。</p>
<p>例如,最常见的汽车头尾信号灯、电梯运行等都主要是用开关量控制的。</p>
<h2 id="keil-c51的应用">KEIL C51的应用</h2>
<ul>
<li>C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。</li>
<li>使用C语言进行程序设计已经成为软件开发的一个主流。</li>
<li>用C语言开发系统可以大大缩短开发周期,明显增强程序的可读性,便于改进和扩充。</li>
<li>而针对8051的C语言日趋成熟,成为了专业化的实用高级语言。</li>
</ul>
<h3 id="-c-51的特点">㈠ C-51的特点</h3>
<p>C语言作为一种非常方便的语言而得到广泛的支持,国内最通用的是Keil C51.</p>
<p>C语言程序本身不依赖于机器硬件系统,基本上不作修改就可将程序从不同的单片机中移植过来。</p>
<p>C提供了很多数学函数并支持浮点运算,开发效率高,故可缩短开发时间,增加程序可读性和可维护性。</p>
<p>C-51与ASM-51相比,有如下优点:</p>
<ol>
<li>对单片机的指令系统不要求了解,仅要求对8051 的存贮器结构有初步了解;</li>
<li>寄存器分配、不同存贮器的寻址及数据类型等细节可由编译器管理;</li>
<li>程序有规范的结构,可分成不同的函数,这种方式可使程序结构化;</li>
<li>具有将可变的选择与特殊操作组合在一起的能力,改善了程序的可读性;</li>
<li>提供的库包含许多标准子程序,具有较强的数据处理能力;</li>
<li>由于具有方便的模块化编程技术,使已编好程序可容易地移植;</li>
</ol>
<h3 id="c51存储类型">C51存储类型</h3>
<table>
<thead>
<tr>
<th>存储类型</th>
<th>寻址空间</th>
<th>数据长度</th>
<th>值域范围</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>片内直接寻址 RAM</td>
<td>8</td>
<td>0~127</td>
</tr>
<tr>
<td>idata</td>
<td>片内间接寻址 RAM</td>
<td>8</td>
<td>0~255</td>
</tr>
<tr>
<td>pdata</td>
<td>分页寻址片外 RAM</td>
<td>8</td>
<td>0~255</td>
</tr>
<tr>
<td>xdata</td>
<td>片外数据存储 (64K)</td>
<td>16</td>
<td>0~65535</td>
</tr>
<tr>
<td>code</td>
<td>片内统一编址ROM (64K)</td>
<td>16</td>
<td>0~65535</td>
</tr>
<tr>
<td>bdata</td>
<td>片内可位寻址的RAM (16byet)</td>
<td>1</td>
<td>0~127</td>
</tr>
</tbody>
</table>
<p>C51的数据声明的一般格式如下:</p>
<pre><code>[类型说明符][修饰符] 标识符[=初值]……
</code></pre>
<p>例如:<code>unsigned char code Flag = 0x0f;</code>就是声明一个无符号的char型变量Flag,并给他赋初值为0x0f;并且声明他所在的存储空间在片内统一编址的ROM中。</p>
<p>声明中,如果没有修饰符,则数据默认的存储空间为data型,也就是在片内RAM中。</p>
<h3 id="-c51的程序结构">㈡ C-51的程序结构</h3>
<p>与一般C语言的结构相同,以main()函数为程序人口,程序体中包含若干语句还可以包含若干函数。</p>
<p>C-51函数的一般格式:</p>
<pre><code class="language-c">类型 函数名(参数表)
{
数据说明部分
语句执行部分
}
</code></pre>
<h3 id="-c51的数据类型">㈢ C-51的数据类型</h3>
<p>基本数据类型:</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>符号</th>
<th>关键字</th>
<th>所占位数</th>
<th>数的表示范围</th>
</tr>
</thead>
<tbody>
<tr>
<td>整型</td>
<td>有</td>
<td>(signed) int</td>
<td>16</td>
<td>-32768~32767</td>
</tr>
<tr>
<td></td>
<td></td>
<td>(signed) short</td>
<td>16</td>
<td>-32768~32767</td>
</tr>
<tr>
<td></td>
<td></td>
<td>(signed) long</td>
<td>32</td>
<td>-2147483648~2147483647</td>
</tr>
<tr>
<td></td>
<td>无</td>
<td>unsigned int</td>
<td>16</td>
<td>0~65535</td>
</tr>
<tr>
<td></td>
<td></td>
<td>unsigned short int</td>
<td>16</td>
<td>0~65535</td>
</tr>
<tr>
<td></td>
<td></td>
<td>unsigned long int</td>
<td>32</td>
<td>0~4294967295</td>
</tr>
<tr>
<td>实型</td>
<td></td>
<td>有</td>
<td>float</td>
<td>32</td>
</tr>
<tr>
<td></td>
<td>有</td>
<td>double</td>
<td>64</td>
<td>1.7e-308~1.7e308</td>
</tr>
<tr>
<td>字符型</td>
<td>有</td>
<td>char</td>
<td>8</td>
<td>-128~127</td>
</tr>
<tr>
<td></td>
<td>无</td>
<td>unsigned char</td>
<td>8</td>
<td>0~255</td>
</tr>
</tbody>
</table>
<p>扩充定义:</p>
<ul>
<li>sfr: 特殊功能寄存器声明</li>
<li>sfr16: sfr的16位数据声明</li>
<li>sbit: 特殊功能位声明</li>
<li>bit: 位变量声明</li>
</ul>
<p>例:</p>
<pre><code class="language-c">sfr SCON = 0X98;
sfr16 T2 = 0xCC;
sbit OV = PSW^2;
</code></pre>
<h3 id="-c-51数据的存储类型">㈣ C-51数据的存储类型</h3>
<table>
<thead>
<tr>
<th>名称</th>
<th>存储空间位置</th>
<th>长度</th>
<th>数据范围</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>直接寻址片内RAM</td>
<td>8位</td>
<td>0~255</td>
</tr>
<tr>
<td>bdata</td>
<td>可位寻址片内RAM</td>
<td>1位</td>
<td>0/1</td>
</tr>
<tr>
<td>idata</td>
<td>间接寻址片内RAM</td>
<td>8位</td>
<td>0~255</td>
</tr>
<tr>
<td>pdata</td>
<td>片外页RAM</td>
<td>8位</td>
<td>0~255</td>
</tr>
<tr>
<td>xdata</td>
<td>片外RAM</td>
<td>16位</td>
<td>0~65535</td>
</tr>
<tr>
<td>code</td>
<td>程序ROM</td>
<td>16位</td>
<td>0~65535</td>
</tr>
</tbody>
</table>
<p>例:</p>
<pre><code class="language-c">数据类型 存储类型 变量
char data bit data unsigned
var1; flags; char xdata
vextor;
</code></pre>
<h3 id="-c-51的包含的头文件">㈤ C-51的包含的头文件</h3>
<p>通常有: reg51.h、math.h、ctype.h、stdio.h、stdlib.h、absacc.h</p>
<p>常用有:</p>
<ul>
<li>reg51.h (定义特殊功能寄存器和位寄存器)</li>
<li>math.h (定义常用数学运算)</li>
</ul>
<h3 id="-c-51的运算符">㈥ C-51的运算符</h3>
<p>与C语言基本相同:</p>
<ul>
<li><code>+</code>、<code>-</code>、<code>*</code>、<code>/</code> (加、减、乘、除)</li>
<li><code>></code>、<code>>=</code>、<code><</code>、<code><=</code> (大于、大于等于、小于、小于等于)</li>
<li><code>==</code>、<code>!=</code> (测试等于、测试不等于)</li>
<li><code>&&</code>、<code>||</code>、<code>!</code> (逻辑与、逻辑或、逻辑非)</li>
</ul>
<h3 id="-c-51的基本语句">㈦ C-51的基本语句</h3>
<p>与标准C语言基本相同:</p>
<ul>
<li>if 选择语言</li>
<li>switch/case 多分支选择语言</li>
<li>while 循环语言</li>
<li>do-while 循环语言</li>
<li>for 循环语言</li>
</ul>
<h3 id="-中断服务程序">㈧ 中断服务程序</h3>
<pre><code class="language-c">函数名()interrupt n
{}
</code></pre>
<h3 id="-io口定义">㈨ I/O口定义</h3>
<pre><code class="language-c">#include <absacc.h>
#define prot xbyte
</code></pre>
<p>或用指针定义</p>
<p>例:清零程序 (将2000H—20FFH的内容清零)</p>
<p>★ 汇编语言程序</p>
<pre><code>ORG 0000H
SE01: MOVR0,#00H
MOVDPTR,#2000H;(0000H)送DPTR
LOO1: CLRA
MOVX @DPTR,A ;0送(DPTR)
INCDPTR ;DPTR+1
INCR0 ;字节数加1
CJNE R0,#00H,LOO1 ;不到FF个字节再清
LOOP: SJMP LOOP
</code></pre>
<p>★ C-51程序</p>
<pre><code class="language-c">#include <reg51.h>
main( )
{
int i;
unsigned char xdata *p=0x2000;
/* 指针指向2000H单元 */
for(i=0;i<256;i++)
{*p=0; p++;}/*清零2000H-20FFH单元*/
}
</code></pre><br><br>
来源:https://www.cnblogs.com/jacx93/p/18119025
頁:
[1]