注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
zjjone1023的个人空间 https://home.eeworld.com.cn/space-uid-144059.html [收藏] [复制] [分享] [RSS]
日志

MSC-51单片机学习笔记之3

已有 2311 次阅读2011-5-24 00:39 |

                   第4 MCS-51汇编语言程序设计

本章重点

        汇编语言与机器语言、高级语言的区别

              汇编语言程序语句格式

              两次扫描汇编过程

              Intel HEX文件格式

              汇编语言程序的流程控制结构

4.1、汇编语言的概述

1、机器语言:计算机能够直接识别和执行的只有二进制编码的指令,这种编码形式就是机器语言

例如:74H 34H 24H 45H F5H 09H 74H 12H 34H 23H F5H 08H

2、汇编语言:使用助记符、符号地址、标号等符号来编写程序的系统称为汇编语言

例如:RES_LOW   DATA   09H

         RES_HIGH  DATA    08H

                     MOV    A,#34H

                              ADD     A.#45H

                 ………..

3、高级语言:面向过程和问题并能独立于机器的通用程序设计语言,是一种接近人类自然语言和常用数学表达式的计算机语言

例如:int a,b,c

      a=0x1234;

         b=0x1235;

         c=a+b;

在科学计算、信息处理等方面采用高级语言比较合适,而在实时控制中,通常使用汇编语言

 

4.2汇编语言格式

4.2.1程序语句格式:汇编语言中的语句包括指令语句、汇编语句伪指令语句、汇编控制语句和注释语句

         指令语句就是可执行的指令助记符,伪指令语句是汇编器的指令,汇编控制语句用来设置汇编器模式和工作流程,注释语句用来说明以上语句的目的,提高程序可读性

    汇编语句一般    [标号:]           助记符    [操作数列表]   [;注释]

                                   [标号或符号:]     伪指令    [操作数]       [;注释]

4.2.2表达式:位于操作数字段的数据有三种表示方法:显示记法(如0FFH),使用预定义的符号(如ACC),也可以使用表达式,如2-3,表达示求值都按16位运算进行

         A、数制:可以在常数结尾处加符号标注来表示数值的进制,通常B表示二进制,OQ表示八进制,H表示十六进制,D或者不加表示十进制

         B、字符和字符串:字符串以一个或两个单引号引起来的字符构成,可用在操作数字段的表达式中,汇编器将其ASCII码转换为等价的二进制形式,如MOV A,#’0’

         C、算术运算:包括加(+),减(-),乘(*),除(/),求模(MOD

         D、逻辑运算:或(OR),与(AND),异或(XOR),非(NOT

         E、特殊运算:右移(SHR),左移(SHL,取高字节(HIGH,取低字节(LOW),优先求值(())

         F、关系运算:相等(EQ、=),不相等(NE<>,小于(LT<),小于或等于(LE<=,大于(GT>),大于或等于(GE>=)

         运算优先级从高到低如下

()

HIGH  LOW

*   /

+   -

EQ(=)   NE(<>)   LT(<)   LE(<=)  GT(>)  GE(>=)

NOT

AND

OR   XOR

同级别的结合性为从左到右

4.2.3伪指令语句:只是指定汇编器在对源程序汇编期间需要执行的一些操作

       AORG:设置汇编计数器的值,指定其后语句的起始地址

       BEND:是源程序的最后一条语句,用以通知汇编程序汇编过程应在此结束

       CEQUSETEQU   symbol     EQU   expression      ,为常数符号symbol指定一个数值,即表达式expression的结果,SET类似于EQU,二者区别在于EQU定义的符号不允许重新定义,而使用SET定义的符号可以重新定义

       DDATAIDATAXDATABITCODE:用来给相应的段(存储区域)内地址赋一个符号分别对应内部RAM、间接寻址的内部RAM、外部RAM、位寻址区、程序存储器区域

EDS:以字节单位保留存储空间   [lable]    DS   expression    汇编时地址计数器的值将会更新为当前值与expression结果的和

FDBIT以位为单位保留存储空间   [lable]    DBIT  expression

GDB以字节为单位初始化程序存储器空间   [lable]    DB   expression[expression][……….]

HDW以双字节为单位初始化程序存储器空间,格式同上

IPUBLICEXTRN:模块间通信的伪指令,连接各个子程序等等

PUBLIC     symbol[,sybol][………]

J、绝对地址选择伪指令

CSEG    [AT    address]  程序存储器指定绝对地址

CSEG    [AT    address]  内部数据….

CSEG    [AT    address]  间接寻址的内部数据……

CSEG    [AT    address]  位寻址区和外部数据…….

CSEG    [AT    address]  和外部数据…….

4.2.5条件汇编:允许将一个软件的多个版本保存在同一组源程序文件中,使用IFELSEIFELSEENDIF一般格式为

IF   expression

       (语句组1

ELSE

       (语句组2

ENDIF

或者

IF       expression1

          (语句组1 

ELSEIF  expression2

       (语句组2

[ELSEIF  expressionX

              (语句组X]

ELSE

              (语句组X+1

ENDIF

4.2.6程序结构:程序员经验的总结,通常的顺序是:版本号定义部分,常数符号定义部分,存储区符号定义部分,指令代码部分

 

4.3汇编程序的工作过程

4.3.1手工汇编过程:通常手工汇编要两次完成

         第一次扫描时应该先确定源程序在内存的起始地址,然后在指令码表中依次找出每条指令的操作码,从程序的起始地址开始,逐一将它们写出。

         第二次扫描是第一次的继续,其任务是确定第一次扫描过程序中未确定的标号或地址位移量的值

例题:MCS51单片机内部RAM30H31H单元存放着两个8位无符号数,求出其中最大者存放到32H单元中,使用CJNE指令完成无符号数的比较,程序如下

NUM1  DATA   30H

NUM2  DATA   31H

NUM3  DATA   32H

           ORG    0000H

MAIN:

              MOV    A,NUM1

              CJNE    A,NUM2   NUM_NEQ

              MOV    NUM3,NUM1

              SJMP    OVER

MUN_NEQ:

              JC      LATTER

              MOV    NUM3,NUM1

              SJMP    OVER

LATTER:

              MOV    NUM3,NUM2

OVER:

              SJMP    $

              END

这里包含一个ORGEND伪指令语句的完整程序,第一扫描时要查指令表,并写下每条指令的机器码及其起始地址,对于无法确定的位移量、目标地址等,应该照原样写在操作数的相应位置上,如表41所示

地址

机器码

标号

指令助记符

0000H

02 MAIN

 

LJMP MAIN

0030H

E5 30

MAIN

MOV  A,NUM1

0032H

B5 31 NUM_NEQ

 

CJNE A,NUM2,NUM_NEQ

0035H

85 30 32

 

MOV  NUM3,NUM1

0038H

80 OVER

 

SJMP VOER

003AH

40 LATTER

NUM_NEQ

JC   LATTER

003CH

85 30 32

 

MOV  NUM3,NUM1

003FH

80 OVER

 

SJMP VOER

0041H

85 31 32

TATTER

MOV  NUM3,NUM2

0044H

80 $

OVER

SJMP $

第二次扫描要确定机器码中的标号或地址位移量,就是计算出表4-1中的MAINNUM_NEQOVERLATTER$等所对应的实际值,其中MAIN的值为0030HOVER的值为0044HLATTER的值为0041H,除了MAIN可以直接填写外,其他都涉及相对寻址,所以要计算出位移量

0034H单元的NUM_NEQ=003AH-0035H=05H,0039H单元的OVER=0044H-003AH=0AH,003BH单元的LATTER=0041H-003CH=05H,0040H单元的OVER=0044H-0041H=03H0045H单元的$=0044H-0046H=-2=FEH,将计算结果填入表中得到表4-2如下

地址

机器码

标号

指令助记符

0000H

02 00 30

 

LJMP MAIN

0030H

E5 30

MAIN

MOV  A,NUM1

0032H

B5 31 05

 

CJNE A,NUM2,NUM_NEQ

0035H

85 30 32

 

MOV  NUM3,NUM1

0038H

80 0A

 

SJMP VOER

003AH

40 05

NUM_NEQ

JC   LATTER

003CH

85 30 32

 

MOV  NUM3,NUM1

003FH

80 03

 

SJMP VOER

0041H

85 31 32

TATTER

MOV  NUM3,NUM2

0044H

80 FE

OVER

SJMP $

 

4.3.2机器汇编过程:手工汇编简单易行,但效率低容易出错,特别是在源程序较长,复杂时,实际应用中都采用机器汇编来完成,机器汇编通常也是两次扫描汇编,为完成两次扫描需要以下基本数据:

各个段的址计数器LC,用以跟踪和确定符号和指令的地址。

指令机器码表MOT,用以确定指令的长度和把助记符转换为机器码

符号表SYMBOL,在第一扫描时,把各个标号、符号的值列入表中,以便第二次扫描时代入相应的符号地址中

伪指令操作表POT,汇编过程序中遇到伪指令时执行相应的操作

输入汇编源程序

实现两次扫描汇编程序的算法可描述如下

读源程序

查找MOTPOT

分析源程序行的语法(检查语法有没有错误)

跟踪地址计数器LC

建立符号表

计算地址

写出目标程序

4.3.3 inter HEX文件

HEX文件是一种把二进制机器码保存为ASCII字符文件的标准。若存储在磁盘上,由于一个字节数据需要两个十六进制符号表示,HEX文件所占空间比二进制格式要大一倍,例如对上例题的对应的HEX文件内容如下

:03000000020030CB

:10003000E530B53105853032800A400585303280A3

:060040000385313280FE51

:00000001FE

HEX文件一般有多行,每行以冒号开始,格式为

CCAAAATTDDDDDDDDDDDDDDDDDDDDSS

数据全部使用十六进制表示,其中,CC是计算字节,指示该行有多少个机器码字节,CC的范围是0010,即从0-16AAAA为加载地址,指出该行第一个机器码字节在程序存储器中的单元地址,是用4位十六进制数表示的16位地址,TT为类型,01表示该行为文件未行,00表示非未行,DD……DD是实际机器码(包括程序中的常数表格),这部分最多有16个字节的数据,对程序存储器编程时,这部分内容输入到程序存储器的连续单元中,SS为校验字节,即校验和的形式,将该行包括SS在内的所有字节相加,丢弃进位后结果应该为0

例如解释以下HEX文件信息,并检查是否有存储错误

:060040000385313280FE51

:00000001FE

第一行有6个字节机器码,从程序存储器0040H单元开始存放,非最后一行,机器码分别为03H85H13H80HFEH:06H+00H+40H+00H+03H+85H+31H+32H+80H+FEH=0,无校验错

第二行有0个字节机器码,是文件的最后一行,00H+00H+00H+01H+FFH=0,无校验错

 

4.4汇编语言设计

汇编语言程序设计一般过程是:分析任务,确定算法或解题思路,按功能划分模块,确定各模块之间的相互关系及参数传递;若问题较复杂,应根据算法和钥匙思路画出程序流程图;合理分配寄存器和存储器,编写汇编语言源程序,并附以必要的注释;进行汇编和连接;软件或硬件仿真调试、修改,直到满足任务要求;将调好目标文件(二进制或HEX格式)写入程序存储器内,上电运行,

根据结构化程序设计特点,程序有三种基本结构:顺序结构、分支结构和循环结构,为实现模块化,也经常使用子程序

如图1所示。
 

4.4.1顺序结构
例1、设在外RAM的60H单元存有1个字节代码,要求将其分解成两个4位字段,高4位存入原单元的低4位,其低4位存入61H单元的低4位,且要求这两个单元的高4位均为0,试编制完整程序。
解: 字节分解:

 

核心指令

MODE:

ANL
ORL 1000H
MODE:MOV R0,#60H
MOVX A,@R0
MOV B,A
ANL A,#0F0H
SWAP A
MOVX @R0,A
ANL B,#0FH
MOV A,B
INC R0
MOVX @R0,A
END


4.4.2分支结构与分支程序设计
结构:根据不同的条件,进行相应的处理。
通常用条件转移指令形成简单分支结构。
如: 判(A) = Z 或 NZ ,转移
判(CY)= 1 或 0 ,转移
判(bit)=1 或 0 ,转移
CJNE 比较不相等转移
例3、设a存放在累加器A中,b存放在寄存器B中,要求按下式计算Y值,并将结果Y存于累加器A 中,试编写程序。


解:本题关键是判a是正数,还是负数;由ACC7便知。

 


BR:



MINUS:
DONE:

ORG 1000H
JB ACC7,MINUS
CLR C
SUBB A,B
SJMP DONE
ADD A,B
SJMP $
END

例4、设有两个16位无符号数NA,NB分别存放在8031单片机内部RAM的40H、41H及50H、51H单元中,当NA > NB时,将内部RAM的42H单元清0;否则,将该单元置成全1,试编程。
解法I:因为无16位数的比较指令,所以,只能用8位数的比较指令。
(画出流程框图)

 


CMP:




CMP1:


HIGHE:
DONE:

ORG 2000H
MOV A,50H
CJNE A,40H,CMP1
MOV A,51H
CJNE A,41H,CMP1
SJMP NHIGHE
JC HIGHE
NHIGHE:MOV 42H,#0FFH
SJMP DONE
MOV 42H,#00H
SJMP $
END

上述程序中多次用到SJMP语句,该语句为无条件转移语句。无条件语句应尽量少用,这样可使程序结构紧凑而易读,易理解。

解法II:先假设NA > NB,再来判断是否NA ≤ NB

 


CMP2:





CMP3:
NHIGHE:
HIGHE:

ORG 3000H
MOV R0,#00H
MOV A,50H
CJNE A,40H,CMP3
MOV A,51H
CJNE A,41H,CMP3
SJMP NHIGHE
JC HIGHE
MOV R0,#0FFH ;不大于标志
MOV 42H,R0
SJMP $
END

 

4.4.3循环结构

循环结构不但使程序简练,而且大大节省存储空间。
循环程序包含四部分:
初始化部分
循环处理部分(主体)
循环控制部分(修改地址指针、修改变量、检测循环结束条件)
循环结束部分(对结果分析、处理,存放结果)

循环有:单循环、多重循环。
循环次数已知,可用计数器控制循环次数;
循环次数未知,按问题条件控制循环是否结束。
一、单循环程序
1、循环次数是已知的程序
例1、已知片外RAM的10H单元存放8位二进制数,要求将其转移成相应的ASCII码,并以高位在前,低位在后的顺序,依次存放到片外RAM以11H为首地址的连续单元中,试编程。


解:先将中间单元置成30H,然后判欲转换位是否为1,
若是,则将中间单元内容加1;否则,中间单元内容保持不变。
通过左移指令实现由高到低的顺序进行转换。

  ORG 1000H  
START:
MOV R2,#08H ;循环计数初值(循环次数已知)
MOV R0,#10H ;地址指针初值
MOVX A,@R0 ;取数
MOV B,A ;暂存B中
LOOP:
MOV A,#30H ;将中间单元(A)置成30H
JNB B.7,NA ;判断转换的二进制位为0否?
  ;若是转NA
INC A ;1的ASCII码“31H”
NA:
INC R0 ;修改地址指针
  MOVX @R0,A ;存放转换的结果
  MOV A,B  
  RL A,B ;作好准备,判断下一位
  MOV B,A ;暂存
  DJNZ R2,LOOP ;判断转换结束否?未完继续
  SJMP $  
  END  

2)循环次数未知的程序

例2、设用户用键盘输入长度不超过100字节的字符串放在8031单片机外部RAM以20H为首地址的连续单元,该字符串用回车符CR(‘CR’= 0DH)作为结束标志,要求统计此字符串的长度并存入内部RAM的1FH单元中。
解:从首单元开始取数,每取一数判断其是否为‘CR’,是则结束。

 


STADA
SLANG

CMCR2:

CRLOP:
ORG 1000H
DATA 20H
DATA 1FH
MOV R0,#STADA-1
MOV B,#0FFH
INC R0
INC B
MOVX A,@R0
CJNE A,#0DH,CRLOP
MOV SLANG,B
SJMP $
END

2、多重循环设计
循环体中还包含着一个或多个循环结构,即双重或多重循环。
例3、设8031使用12MHz晶振,试设计延迟100ms的延时程序。
解:延时程序的延迟时间就是该程序的执行时间,通常采用MOV和DJNZ二指令。
T = 12 / fosc = 12 / (12×106)= 1us

 
内循环延时:
(1 + 2 × CTR)T = 500us(假设)
则CTR = 250
实际延时:[1 + 2 × 250] × 1us = 501us

外循环延时:T +(501 + 2T)× CTS = 100ms = 100 000us
所以 , CTS = 198.8 取 199
实际延时:[1 + (501 + 2)×199] = 1000.98ms

例4、设在8031内部RAM中存一无符号数的数组,其长度为100,起始地址是30H,要求将它们从大到小排序,排序后仍存放在原区域中,试编者按程。

 

这就是所畏的“冒泡法”。
实际上大多情况,用不到99次循环,排序就结束。为了提高排序速度,程序中可设一交换标志位,如10H位,
每次循环中:若有交换则 SETB 10H
若无交换则 CLR 10H
每次循环结束时,测10H位,判断排序是否结束。


BUBBLE:



LOOP:




BUEU:






BUNEXT:

ORG 1000H
MOV R0,#30H
MOV B,#64H
CLR 10H
DEC B
MOV A,@R0
MOV 20H,A
INC R0
MOV 21H,@R0
CJNE A,21H,BUEU
JNC BUNEXT
MOV A,@R0
MOV @R0,20H
DEC R0
MOV @R0,A
INC R0
SETB 10H
DJNZ B,LOOP
JB 10H,BUBBLE
END





;长度计数
;暂存,为交换作准备


;若(20H)≠(21H)转移
;(20H)≥(21H)转移
;若(20H)< (21H)则交换

;使R0退格指向小地址

;恢复R0指向大地址
;置交换标志

;判断标志位为1否?若为1,则继续

 

 

 

发表评论 评论 (8 个评论)
回复 xu__changhua 2011-5-28 00:50
表达示求值都按16位运算进行
=================
谁说的?
回复 xu__changhua 2011-5-28 00:57
[标号:]             助记符    [操作数列表]   [;注释]
[标号或符号:]     伪指令    [操作数]       [;注释]
==============================
伪指令前的标号或符号后只要空格而不该有【冒号】
;;;;
你的大标题是MSC-51单片机学习,可夹杂着86的内容
回复 xu__changhua 2011-5-28 01:02
4.3.2  这一段,是{编译系统}知识,又是一门专门课程。我们计算机的应用者可以不必关心它的编译(或汇编)过程,只要知道机器能代替我们翻译指令就可以了。
回复 zjjone1023 2011-5-29 13:30
xu__changhua: [标号:]             助记符    [操作数列表]   [;注释]
[标号或符号:]     伪指令    [操作数]       [;注释]
==============================
伪指令前的标
我这些都是按照书上学习的,每天带着看一点内容,现学的东西只能依靠书,而且也不知道对不对
回复 zjjone1023 2011-5-29 13:32
xu__changhua: 表达示求值都按16位运算进行
=================
谁说的?
书是这么说的,书名叫单片机原理与接口技术
我作笔记一个很大的原因也是想各个老师能看到,指出我们学习的错误
回复 xu__changhua 2011-6-1 08:56
那是错的
回复 xu__changhua 2011-6-1 08:58
也是错的
回复 zjjone1023 2011-6-1 21:38
错在哪里了,老师说说看,怎么样是对的

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章