delay1000ms:(HT46R65的单片机)(注意不要开启计时中断允许位)
mov a,10000111b (设置频率和记数方式)(上升记数还是下降记数)
mov tmr0c,a (tmr0c 计数器的控制寄存器)
mov a,low(65536-31250) (设置的频率就是1S上升31250)因此是DELAY1S
mov TMR0L,a (计数器的赋予初始值的低位寄存器)
mov a,high(65536-31250)
mov TMR0h,a(计数器的赋予初始值的高位寄存器)
set tmr0c4 (打开记数)
snz intc06 (是否有中断请求标志)(有就跳过)
jmp $-1 (退回一步)
clr tmr0c4 (关闭记数)
clr intc06 (清除中断标志)
ret
CODE SEGMENT
ASSUME CS:CODE
ORG 100H
START: PUSH CS
POP DS
PUSH CS
POP ES
MOV DI,0
MOV SI,0
MOV BX,10
@MAIN1: MOV CX,BX
CALL FACT
ADD SI,AX
ADC DI,DX
DEC BX
JNZ @MAIN1
MOV AX,SI
MOV DX,DI
CALL DISPDXAX
MOV AH,4CH
INT 21H
;=====================================
; cx中存放要求阶乘的数
; 阶乘结果在dx、ax中
FACT PROC NEAR
PUSH BX
PUSH SI
PUSH DI
PUSHF
MOV DX,0
MOV AX,1
@FACT1: MOV BX,CX
CALL MULT
LOOP @FACT1
POPF
POP DI
POP SI
POP BX
RET
FACT ENDP
;========================================================
; 无符号乘法子程序 (mul指令只能实现16位乘16位,
; 本子程序实现32位乘16位--限定数的大小,结果仍为32位)
; 被乘数放置于dx,ax 中, 乘数放置于 bx中
; 结果放置于dx,ax中(dx为高16位,ax为低16位)
MULT PROC NEAR
PUSH CX
PUSH SI
PUSH DI
PUSHF
MOV SI,0
MOV DI,0
CMP BX,0
JE @MULTEXIT
@MULT1: SHR BX,1
JNC @MULT2
ADD SI,AX
ADC DI,DX
@MULT2: SHL AX,1
RCL DX,1
CMP BX,0
JNE @MULT1
MOV DX,DI
MOV AX,SI
POPF
POP DI
POP SI
POP CX
RET
@MULTEXIT:
MOV AX,0
MOV DX,0
POPF
POP DI
POP SI
POP CX
RET
MULT ENDP
;============================================
; 将要显示的32位无符号数置于dx、ax中
DISPDXAX PROC NEAR
MOV WORD PTR [Y],AX
MOV WORD PTR [Y+2],DX
; 以下将 Y (16进制)转为10进制串并输出
MOV AX,WORD PTR [Y]
MOV DX,WORD PTR [Y+2]
MOV BX,WORD PTR [Z]
MOV CX,WORD PTR [Z+2]
MOV WORD PTR N,0
MM0: INC WORD PTR N
SUB AX,BX
SBB DX,CX
JNC MM0
DEC WORD PTR N
ADD AX,BX
ADC DX,CX
MOV WORD PTR[Y],AX
MOV WORD PTR[Y+2],DX
MM1: LEA DI,CC
ADD DI,9
M2:
MOV AX,WORD PTR [Y]
MOV DX,WORD PTR [Y+2]
MOV BX,10000
DIV BX
PUSH AX
PUSH DX
; 以下转换10进制的低4位
POP DX
MOV CX,4
MOV AX,DX
M3: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M3
; 以下转换10进制的高万位
POP AX
MOV CX,1
M4: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M4
MOV AX,WORD PTR N
MOV CX,5
M5: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M5
; 输出换行回车
LEA DX,LFCR
MOV AH,9
INT 21H
; 输出两数的和的10进制串
LEA DX,CC
MOV AH,9
INT 21H
RET
Y DD
CC DB 10 DUP(' '),10,13,'$'
LFCR DB 10,13,'$'
Z DD 100000
N DW 0
DISPDXAX ENDP
CODE ENDS
END START
子程序中一般不能用JMP跳出,否则会造成地址混乱,因为调用子程序时会有堆栈 *** 作,将当前地址压栈,子程序返回时会出栈恢复地址,如果用JMP指令,那么就没有出栈 *** 作了,多调用几次,就可能造成堆栈溢出,从而程序就乱了。
汇编语言中主程序与子程序参数传递的方法有以下几种:
1寄存器法
寄存器法就是将入口参数和出口参数存放在约定的寄存器中。
优点:数据传递书读快、编程较方便、节省内存单元。
缺点:当传递参数过多时候,由于寄存器个数有限,及寄存器的频繁使用,将导致寄存器不足。
适用:参数较少的子程序
2。约定单元法:
约定单元法顾名思义是吧入口参数和出口参数都放在事先约定好的单元中
优点:不占用寄存器、参数个数任意、每个子程序要处理的数据和送出的结构都有独立的存储单元
缺点:但用一定数量的存储单元,增加编程中对变量定义的难度
3堆栈法
堆栈法是利用堆栈来传递参数的。
优点:参数不占用寄存器,和存储单元。参数存放在公共堆栈区,处理完后客恢复。参数个数一般不限
缺点:由于参数和子程序混杂在一起,存取参数时候必须小心计算它在堆栈中的位置。要注意断点的保存和恢复。
4地址表法
这种方法是把参数组成的一张参数表放在某个存储区中,然后只要主程序和子程序约定好这个存储区的首地址和存放的内容,在主程序中将参数传递给地址表,在子程序中根据地址表给定的参数就可以完成 *** 作。
DATAS SEGMENT
CIPHER db 'ASDSFASGDFFGFJJFGYZ'
LEN DW $-CIPHER
CHAR DB 26 DUP(0)
DATAS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
START:
MOV AX,DATAS
MOV DS,AX
XOR AX,AX
MOV SI,OFFSET CIPHER
MOV CX,LEN
L1:
MOV BX,OFFSET CHAR
MOV AL,[SI]
SUB AL,41H
ADD BX,AX
ADD BYTE PTR [BX],1
INC SI
DEC CX
JNZ L1
MOV CH,26
MOV DL,41H
L3:
PUSH DX
MOV BL,DL
MOV DL,20H
MOV AH,2H
INT 21H
MOV DL,BL
MOV AH,2H
INT 21H
MOV DL,20H
MOV AH,2H
INT 21H
POP DX
INC DL
DEC CH
JNZ L3
MOV DL,0DH
MOV AH,2H
INT 21H
MOV DL,0AH
MOV AH,2H
INT 21H
MOV CH,26
MOV SI,OFFSET CHAR
MOV CL,4
L2:
mov bl,[si]
mov dl,bl
rol dl,cl
and dl,0fh
add dl,30h
mov ah,2h
int 21h
mov dl,bl
and dl,0fh
add dl,30h
mov ah,2h
int 21h
mov dl,20h
mov ah,2h
int 21h
inc SI
dec CH
jnz L2
MOV AH,4CH
INT 21H
CODES ENDS
END START
; 本程序在MASMPlus 12集成环境下通过编译,经过调试,运行正确。
Code Segment
Assume CS:Code,DS:Code
; -------------------------------------
; 功能:显示指定地址(Str_Addr)的字符串
; 入口:
; Str_Addr=字符串地址(要求在数据段)
; 用法: Output Str_Addr
; 用法举例:Output PromptStr
Output MACRO Str_Addr
lea dx,Str_Addr
mov ah,9
int 21h
EndM
; -------------------------------------
; 冒泡排序:对从MEM单元开始的N个8位无符号数降序排序
; 入口参数:ds:SI=数组地址,CX=数组元素个数
Bubbling Proc Near
push es
push si
push di
push cx
push ax
push ds
pop es
dec cx ;外循环次数
cld
@@Scanning: push cx ;入栈保存外循环次数
push si ;入栈保存数组地址
@@Compare: mov di,si ;当前数组元素地址赋给目的变址寄存器,以备交换之用
lodsb ;将当前数组元素读入累加器
cmp al,[si] ;当前数组元素与相邻的下一个数组元素相比较
jae @@NextOne ;若大于或等于,不作数据交换,处理下一个数组元素
xchg al,[si] ;若小于,交换数组元素
stosb ;保存数值较小者
@@NextOne: loop @@Compare ;处理下一个数组元素
pop si ;数组地址出栈
pop cx ;外循环次数出栈
loop @@Scanning ;下一趟比较
pop ax
pop cx
pop di
pop si
pop es
ret
Bubbling EndP
; -------------------------------------
MEM db 12,56,253,200,10,99,78,75,63,100
N equ $-MEM
Press_Key db 7,13,10,13,10,'The complated Press any key to exit$'
Start: push cs
pop ds
mov cx,N ;数组元素个数
lea si,MEM ;数组地址
call Bubbling
; -------------------------------------
Exit_Proc: Output Press_Key ;提示 *** 作完成,按任意键结束程序
mov ah,1
int 21h
mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
; -----------------------------------------
; 功能:显示指定地址(Str_Addr)的字符串
; 入口:
; Str_Addr=字符串地址(要求在数据段)
; 用法: Output Str_Addr
; 用法举例:Output PromptStr
Output MACRO Str_Addr
lea dx,Str_Addr
mov ah,9
int 21h
EndM
; -----------------------------------------
; 功能:输出回车换行
Output_CTLF proc Near
push ax
push dx
mov ah,02h
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
Output_CTLF endp
; -----------------------------------------
; 功能:把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示
; 入口:AX=二进制数
; 出口:在当前光标位置显示转换后的ASCII码数字
Dec_ASCII Proc Near
push dx
push bx
push di
mov bx,10
lea di,@@Temp_Save[6]
mov byte ptr [di],'$'
dec di
cld
@@Divide: xor dx,dx
div bx
or dl,30h
mov [di],dl
dec di
test ax,0ffffh
jnz @@Divide
inc di
push di
pop dx
mov ah,9
int 21h
pop di
pop bx
pop dx
ret
@@Temp_Save db 7 dup()
Dec_ASCII EndP
; -----------------------------------------
; 功能:在N个字节数组中查找字符CHAR,并记录该字符出现的次数。
; 入口参数:
; si=一个N字节数的字符串TABLE首地址
; cx=字符串长度,N
; ah=要查找的字符
; 出口参数:bl=该字符出现的次数
Find_Chr Proc Near
@@Find_Chr: lodsb
cmp al,ah ;是指定的字符?
jnz $+4 ;不是
inc bl ;是,计数
loop Find_Chr ;判断下一个字符
ret
Find_Chr EndP
; -----------------------------------------
Prompt_Str db 'Please input a string: $' ;输入字符串提示信息
No_String db 'The string is null$' ;空字符串提示信息
Prompt_Chr db 'Please input a charactor: $' ;输入字符提示信息
Prompt_CNT db 'The specified charactor in th string TABLE: $' ;指定字符出现次数提示信息
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
cld
Input_Str: Output Prompt_Str ;提示输入字符串
lea dx,TABLE ;字符串缓冲区地址
mov ah,0ah
int 21h
call Output_CTLF ;输出一个回车、换行
lea si,TABLE[1] ;实际输入的字符串长度地址
lodsb ;读入这个长度N
test al,0ffh ;N=0?
jnz Read_Chr ;否,转去输入一个字符
Output No_String ;空字符串提示信息
jmp Input_Str ;重新输入字符串
Read_Chr: Output Prompt_Chr ;提示输入字符
mov ah,1 ;从键盘输入一个字符
int 21h
cmp al,1bh
jz Exit_Proc ;若按键为Esc,则结束程序
cmp al,20h ;控制及通讯字符?
jb Read_Chr ;重新输入字符
call Output_CTLF ;输出一个回车、换行
call Output_CTLF ;输出一个回车、换行
push ax
Output Prompt_CNT ;提示指定字符出现次数提示
pop ax
mov ah,al ;指定的字符送ah保存
lea si,TABLE[1] ;实际输入的字符串长度地址
lodsb ;读入这个长度N
mov cl,al
xor ch,ch ;N=cx
xor bl,bl ;计数器,计数指定字符在字符串中出现的次数
call Find_Chr ;在N个字节数组中查找字符CHAR,并记录该字符出现的次数
mov al,bl
xor ah,ah
call Dec_ASCII ;把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示
Exit_Proc: mov ah,4ch ;结束程序
int 21h
TABLE db 255 ; 字符串缓冲区
Code ENDS
END Start ;编译到此结束
以上就是关于单片机。用汇编语言编程。 设计一软件延时1s的子程序。设晶振频率为12MHz。全部的内容,包括:单片机。用汇编语言编程。 设计一软件延时1s的子程序。设晶振频率为12MHz。、用汇编语言设计程序实现10!,并用调用子程序的方法实现1!+2!+3!+……+10!、汇编语言中,我设计了一个子程序,我想问一下在子程序中可以用jmp跳出该子程序吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)