DA_IN: 数据或指令
;RS_STU: 数据指令选择
;WR_COUNT1: 计数器1
;WR_COUNT2: 计数器2
SERIAL_WR: PUSH ACC;A入堆栈保护
MOV A,DA_IN
SETB CS;将CS置1(程序中未定义CS,故不知其作用)
MOV WR_COUNT1,#05H;计数器1置初值5
SETB STD ;将STD置1,标识写数据(程序中未定义STD,故不知其作用,由后面推测可能是用于标识写数据和指令的)
SERIAL_WR1: CLR SCLK;将SCLK置0(程序中未定义CS,故不知其作用)
SETB SCLK;将SCLK置1
DJNZ WR_COUNT1,SERIAL_WR1;计数器1不为0转SERIAL_WR1处
CLR STD ;将STD置0,标识写指令
CLR SCLK;将SCLK置0
SETB SCLK;将SCLK置1
JNB RS_STU,CLR_RS;RS_STU为0(选择为指令)则转CLR_RS处
SETB STD ;RS_STU为1(选择为数据)将STD置1,标识写数据
SJMP SETB_RS;转SETB_RS处
CLR_RS: CLR STD ;将STD置0,标识写指令
SETB_RS: CLR SCLK;将SCLK置0
SETB SCLK;将SCLK置1
CLR STD ;将STD置0
CLR SCLK;将SCLK置0
SETB SCLK;将SCLK置1
MOV WR_COUNT1,#02H;
SERIAL_WR2: MOV WR_COUNT2,#04H;计数器1置初值4
SERIAL_WR21:RLC A;A带进位位循环右移一位
MOV STD,C;C送入STD(即A的最高位送入STD)
CLR SCLK;将SCLK置0
SETB SCLK;将SCLK置1
DJNZ WR_COUNT2,SERIAL_WR21;计数器2不为0转SERIAL_WR21处
MOV WR_COUNT2,#04H;计数器2为0则再置初值4
CLR STD ;将STD置0
SERIAL_WR22:CLR SCLK;将SCLK置0
SETB SCLK;将SCLK置1
DJNZ WR_COUNT2,SERIAL_WR22;计数器2不为0转SERIAL_WR22处
DJNZ WR_COUNT1,SERIAL_WR2;计数器2为0但计数器1不为0转SERIAL_WR2处
CLR SCLK;计数器1为0则将SCLK置0
CLR CS;将CS置0
LCALL DELAY;调用子程序DELAY(延时)
POP ACC;恢复A
RET;返回
另一个
SUB1:JB BUSY,SUB1;设备忙则等待
MOV P0,A;由P0口输出A中数据
NOP ;空 *** 作
SETB REQ;将REQ置1 (程序中未定义REQ,故不知其作用,可能是所用设备中的一个状态标志位)
HE3:JNB BUSY,HE3 ;设备不忙则转HE3处
CLR REQ ;将REQ置0
RET ;返回
HANZI:
MOV A,#0F0H ;数据0F0H送A
ACALL SUB1 ;调用子程序SUB1(输出数据0F0H)
MOV A,#02H ;数据02H送A
ACALL SUB1 ;调用子程序SUB1(输出数据02H)
MOV A,#00H ;数据00H送A
ACALL SUB1;调用子程序SUB1(输出数据00H)
MOV A,#10H ;数据10H送A
ACALL SUB1;调用子程序SUB1(输出数据10H)
MOV A, #01H ;数据01H送A
ACALL SUB1;调用子程序SUB1(输出数据01H)
RET;返回
ASC:
MOV A,#0F1H ;数据0F1H送A
LCALL SUB1 ;调用子程序SUB1(输出数据0F1H)
MOV A,50H ;50H单元中数据0F1H送A
LCALL SUB1;调用子程序SUB1(输出50H单元中数据)
MOV A,51H ;51H单元中数据0F1H送A
LCALL SUB1 ;调用子程序SUB1(输出51H单元中数据)
MOV A,52H ;52H单元中数据0F1H送A
LCALL SUB1;调用子程序SUB1(输出52H单元中数据)
RET;返回
A\D转换
程序设计
AD: MOV 20H,#00H ;数据00H送20H单元
MOV 21H,#00H ;数据00H送21H单元
CLR CLK;将CLK置0
MOV R7,#0AH;;数据0AH送R7
CLR CS;将CS置0
NOP;空 *** 作
LP01: MOV C,DAT;将DAT送入进位位C
MOV A,20H;将20H单元中数送入A
RLC A;A带进位位循环左移一位
MOV 20H,A;A中内容送入20H单元
MOV A,21H;将21H单元中数送入A
RLC A;A带进位位循环左移一位
MOV 21H,A;A中内容送入21H单元(至此是将21H20H整体左移了一位,DAT状态移入20H单元的最低位)
SETB CLK;将CLK置1
CLR CLK;将CLK置0
DJNZ R7,LP01;R7不为0则转LP01处
SETB CS;将CS置1
MOV 22H,20H;20H单元内容送入22H单元
MOV 23H,21H;21H单元内容送入23H单元
RET;返回
change: LCALL AD;调用子程序AD(A\D转换)
MOV 40H,20H;20H单元内容送入40H单元
MOV 41H,21H;21H单元内容送入41H单元
MOV A,41H;41H单元内容送入A
RRC A;A带进位位循环右移一位
MOV 41H,A;A内容送入41H单元
MOV A,40H;40H单元内容送入A
RRC A;A带进位位循环右移一位
MOV 40H,A;A内容送入40H单元
MOV A,41H;41H单元内容送入A
RRC A;A带进位位循环右移一位
MOV 41H,A;A内容送入41H单元
MOV A,40H;40H单元内容送入A
RRC A;A带进位位循环右移一位
MOV 40H,A;A内容送入40H单元(至此41H40H单元内容整体右移了2位,或说是缩小了4倍)
MOV 41H,40H ;40H单元内容送入41H单元
MOV 40H,#00H;40H单元清0
LCALL AD;调用子程序AD(A\D转换)
MOV 40H,20H;20H单元内容送入40H单元
MOV 41H,21H;21H单元内容送入41H单元
MOV 40H,20H;20H单元内容送入40H单元
MOV 41H,21H;21H单元内容送入41H单元
MOV 41H,40H;40H单元内容送入41H单元
MOV 40H,#00H;40H单元清0
MOV A,#5;将数据5送入A
MOV B,41H;41H单元内容送入B
mul ab;AB
mov 33h,b;积的高8位送入33H单元
ret;返回
第一部分的DATA SEGMENT到DATA ENDS属于数据段定义以后你看到SEGMENT/ENDS这对语句括号就可以认为是一个段的定义:SEGMENT表示段定义开始,ENDS表示段定义结束;
这个段中定义了三组字节类型的变量:CHAR,NUM和REZULT,每组可以近似看做高级语言里的数组其中第三个量中的'$',一般是用于字符串定义的结束标志的,尤其是在DOS *** 作系统中常用从你的后部代码看这段程序应该是基于DOS或者早期WINDOWS *** 作系统的
第二部分的STACK SEGMENT到STACK ENDS属于堆栈段定义,定义了100个字节深度的堆栈供你的程序使用;这其中的DUP是一种运算符,是重复定义的意思,重复的次数看其前面的数字
第三部分从CODE SEGMENT开始到最后的END START属于代码段定义就是你处理数据用的指令部分这其中的END语句表示所有源程序结束,应该是你汇编程序里书写的最后一条语句
ASSUME语句是设定语句,是告诉汇编器在将源代码翻译成机器语言时,CPU的各个段寄存器如何与你定义的各个逻辑段相联系比如CS段寄存器就选了CODE代码段
START PROC FAR 到START ENDP表示定义了一个子程序,类似于高级语言里的函数和过程这个子程序 *** 作系统在调用时采用段间调用,你的程序里至少有一个是FAR这个类型的其他几个子程序都由这个START来控制的PROC就表示子程序定义开始,ENDP就表示结束,也是一对语句括号
CALL READ语句前的三条语句完成了对数据段寄存器DS和附加段寄存器ES的初始化这样你代码里就可以直接使用变量名来指代了
CALL READ语句就是80X86汇编里调用子程序的指令这个子程序从READ PROC开始到READ ENDP结束,开头的两条语句是保护现场用的,然后将读取字符保存区域的首地址给了BX,再调用DOS中断21H的01H号功能完成键盘信息读取后面的指令类似完成读取后返回主程序,就是START
不好意思,时间关系,不可能都给你解释了,你可以去找一本讲8086基本汇编和计算机基本数值运算的书看看,对照着就可以翻译出来其实不难的,不要被语句吓倒了
MOV R0, #30H //将立即数30H放入R0
MOV A, @R0 //取地址30H的数据
INC R0 //R0加1后放回R0 R0=31H
ADD A, @R0 //将地址31H内的数据加上A后,放回A
DA A //将A调整为十进制
INC R0 //R0加1后放回R0 R0=32H
MOV @R0, A //将A放入地址32H中
SJMP $ //等待
其实这段是实现了将地址30H和地址31H的相加,最后放入地址32H中
这是一段86汇编程序,其功能是通过系统调用从键盘获取一个输入字符,再通过系统调用将该字符输出显示。程序注释如下:
;
MOV AX, 2000H ; 16进制2000送AX寄存器
MOV DS,AX ; AX寄存器内容送DS寄存器
; 以上两指令将数据段寄存器DS设为2000H
;
MOV AH,1 ; 系统功能号 1 送AH寄存器
INT 21H ; 启动系统调用
; 以上两指令实现读键盘,输入值在AL寄存器
;
MOV [100H],AL ; 输入值存入DS段100H位置
MOⅤ DL,[100H] ; DS段100H单元内容送DL
; 以上两指令将要输出显示字符送DL寄存器。
;
MOV AH,2 ; 系统功能号 2 送AH寄存器
INT 21H ; 启动系统调用
; 以上两指令将DL寄存器内容输出显示。
data segment
num1 db 'please input a number(0-9):',0dh,0ah,'$' ;(这的0dh,0ah起什么作用?回车换行作用如果没有这些,则你输入的数,将出现在please这句话的后面)
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,28bh
mov al,80h
out dx,al
l1: call crlf ;(为什么写入控制字后就开始调用过程?这要看这个被调用的过程有什么作用了)
lea dx,num1
mov ah,09h
int 21h
mov ah,01h
int 21h
cmp al,'0'
jb exit
cmp al,'9'
ja exit
sub al,30h
lea bx,led
xlat
mov dx,288h
out dx,al
jmp l1
exit: mov ah,4ch
int 21h
crlf proc near ;(重点! 这个过程实现什么功能:回车换行作用)
mov dl,0dh ;直接把ODH送入DL就可以实现回车吗:不,现在是先将回车符送入DL,再调用中断显示出来
mov ah,02h ;这个中断指令有什么功能:将DL中的数据,显示在显示屏上
int 21h
mov dl,0ah ;直接把OAH送入到DL就可以实现换行吗:原理同上
mov ah,02h
int 21h
ret
crlf endp
code ends
end start
这个单片机功能是一个只显示2位秒值的电子秒表,最大计数为99秒,有一个按键,兼做启动、停止和复位
按键一次,启动秒表
按键二次,停秒表
按键三次,清初值复位
TCNTA EQU 30H ;定义一个名为TCNTA的变量,它表示为30H的地址,双字节10进制计数器
TCNTB EQU 31H ;定义一个名为TCNTB的变量,它表示为31H的地址
SEC EQU 32H ;定义一个名为SEC的变量,它表示为32H的地址,秒计数
KEYCNT EQU 33H ;定义一个名为KEYCNT 的变量,它的表示为33H的地址,按键计数
SP1 BIT P35 ;SP1表示P35这个位
ORG 00H ;主程序入口向量,单片机启动后从此开始执行
LJMP START ;转到主程序
ORG 0BH ;T0中断向量,发生T0中断时程序转入这里执行
LJMP INT_T0 转移到中断处理程序
START:MOV KEYCNT,#00H ; 主程序
MOV SEC,#00H ;取秒值
MOV A,SEC
MOV B,#10 ;B存放除数
DIV AB ;A/10 A中存放十位数,B中存放个位数
MOV DPTR,#TABLE ;取7段显示码表首地址
MOVC A,@A+DPTR ;十位数查表转换为显示段码
MOV P0,A ;送显示
MOV A,B ;个位数
MOV DPTR,#TABLE
MOVC A,@A+DPTR 个位数查表转换为显示段码
MOV P2,A ;送显示
MOV TMOD,#02H ;定时器工作模式设为定时器0工作在8位定时模式2
SETB ET0 ;启动定时器0
SETB EA ;开中断
WT: JB SP1,WT ;按钮按下
LCALL DELY10MS ;延时10ms
JB SP1,WT ;再次测试,按键去抖
INC KEYCNT ;确定有按钮输入
MOV A,KEYCNT ;按钮计数器+1
CJNE A,#01H,KN1 ;第一次按下按钮
SETB TR0 ;启动计数器
MOV TH0,#06H ;初值=6
MOV TL0,#06H ;计数初值=6
MOV TCNTA,#00H ;清双字节10进制计数器低位
MOV TCNTB,#00H ;清双字节10进制计数器高位
LJMP DKN ;跳转到DKN
KN1: CJNE A,#02H,KN2 ;第二次按下按钮
CLR TR0 ;关闭定时器
LJMP DKN ;跳转到DKN
KN2: CJNE A,#03H,DKN ;第三次按下按钮
MOV SEC,#00H ;秒清0
MOV A,SEC ;取秒
MOV B,#10 ;除数位10
DIV AB ;a/10,A为十位,B为个位
MOV DPTR,#TABLE ;
MOVC A,@A+DPTR
MOV P0,A
MOV A,B
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P2,A
MOV KEYCNT,#00H ;按钮计数清0
DKN: JNB SP1,$ ;按钮松开?未松开,等待
LJMP WT ;已松开,转到等待下一次 *** 作
DELY10MS:
MOV R6,#20 ;这段程序是10ms延时程序
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
INT_T0:
INC TCNTA ;TCNTA+1
MOV A,TCNTA ;
CJNE A,#100,NEXT ;计数到100否?未到,转移到next
MOV TCNTA,#00H ;已到,TCNTA=0
INC TCNTB ;进位到TCNTB
MOV A,TCNTB ;
CJNE A,#4,NEXT ;计数器计满400个数(到一秒)
MOV TCNTB,#00H ;TCNTB=0
INC SEC ;秒+1
MOV A,SEC ;
CJNE A,#100,DONE ;没到100秒。转移到更新显示
MOV SEC,#00H ;秒清0
DONE: MOV A,SEC ;后面同上,是刷新显示
MOV B,#10 ;
DIV AB
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
MOV A,B
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P2,A
NEXT: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;数字01234567890七段码
END
代码有点小问题,改动了一点点后,执行结果是将代码段中的256个值为55的数分别改为:0,1,2,3,4,……一直到255(十六进制为FF),如下:
data segment;数据段
Block db 256 dup(55h);申请首地址为block的256个字节地址空间,每个字节的值均为55h
data ends
code segment;代码段
assume cs:code, ds:data
start procnear;程序开始,将之改成“start:”
mov ax, data
mov ds, ax;这两句的意思是将数据段地址赋给ds
mov bx, offset Block;将首地址block的值赋给bx
mov cx,256;设置cx的值,即为循环次数256次
Again: ;自定义的标号
mov [bx], bl ;将bl的值存入bx所指向的数据段中
inc bx;bx自加1,相当于C语言中的C++
Loop Again;此步是CX-1到CX=0,即循环256次后跳出循环
jmp $;跳转到当前的地址, 所以它是一个死循环,相当于在此原地踏步。如果要让它能正常结束,应该将这句改为“mov ah,4ch int 21h”两句
code ends
end start
以上就是关于汇编语言 中文注释(兄弟答辩用的,谢过诸位了先)全部的内容,包括:汇编语言 中文注释(兄弟答辩用的,谢过诸位了先)、汇编注释、急!汇编语言程序功能和语句注释等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)