汇编语言程序设计(子程序调用+延时输出练习)

1. 使用INT 21H功能调用实现每隔一秒显示A~Z共26个大写字母

思路: 

  • 调用子程序的格式
CALL <过程名>

<过程名> PROC
...
...
RET
<过程名> ENDP
  •  实现延时1s操作,需要用到内外2个循环,3个寄存器BX和CX和AL,内循环设置参数为325,BX计数,相当于1ms,外循环设置循环次数为1000,CX计数,相当于循环1000次1ms,即为1s,AL存1,代表延时的秒数。

  • 若需要延时n秒,则设置AL的次数为n,然后把延时1s的循环操作再循环n次即可,相当于3重循环。

  • 在子程序中用到的CX,主程序中存了其他值,所以需要先PUSH CX的值保存下来,子程序中用完CX后再POP出来。

代码 :

没有用到数据段,不用定义DATA SEGMENT 

CODE    SEGMENT
        ASSUME CS:CODE

        N1MS = 325	;建立延时1ms系数循环计数次数,325是定时常数,经验值


 START: MOV CX,26       ;26个字母
        MOV DL,41H      ;"A"的ASCII码值

A1:     MOV AH,02H
        INT 21H         ;功能调用
        MOV AL,	1	;延时1秒
	CALL DT1S	;调用延时1S子程序

        INC DL          ;切换下一个字母
        LOOP A1

        MOV AH,4CH
        INT 21H         ;程序终止
        

DT1S PROC               ;使用的工作寄存器为:CX、DX,入口参数为AL寄存器,AL的数值为需要延时的秒数。
    PUSH CX

    D0: MOV CX,	1000    ;内循环延时约1ms,外循环为1000次,则内外循环一轮为1秒。
    D1: MOV BX,	N1MS	;建立延时1ms系数循环计数次数
    D2:	DEC BX
	JNZ D2
	DEC CX
	JNZ D1
	DEC AL
	JNZ D0

    POP CX

        RET
DT1S ENDP

CODE    ENDS
        END START


2. 延时练习 

  • 输出数字间的空格,需要在输出每一个数字之后使用2号功能单独输出空格,注意需要先PUSH一下DL的值,因为DL在前面输出数字时一直保存的是数字的ASCII码值,而且后面在输出下一个数字时还需要该值,所以在输出空格的时候需要把DL的值保存下来,输出完空格之后再POP出来,以免影响后续数字输出的工作
  • 在输出“time's up”字符串过程中,在数据段定义字符串的时候,字符'会被当做字符串的分隔符号,因此需要先输出字符串time,再使用2号功能单独输出 ' ('字符的ASCII码值是21H),最后输出字符串s up
;在屏幕第一行显示倒计时3 2 1 go,每隔一秒显示一个数字。
;在屏幕第二行显示倒计时5 4 3 2 1,每隔一秒显示一个数字。
;在屏幕第三行显示字符串 'TIME'S UP!'

DATA SEGMENT
     STR1 DB 'GO!', 0DH, 0AH, '$'    ;0DH, 0AH为回车, 换行的ASCII码
     STR2 DB 0DH, 0AH, 'TIME',27H,'S UP!','$'    ;27H为单引号的ASCII码
DATA ENDS

CODE SEGMENT
     ASSUME CS:CODE,DS:DATA

     N1MS = 275	;建立延时1ms系数循环计数次数

 START: MOV AX,DATA
        MOV DS,AX

        MOV CX,3       ;倒计时3个数
        MOV DL,33H      ;'3'的ASCII码值
        CALL COUNTDOWN     ;显示倒计时321
        
        MOV DX,OFFSET STR1   ; 显示GO!
        MOV AH,9
        INT 21H

        MOV CX,5       ;倒计时5个数
        MOV DL,35H      ;'5'的ASCII码值
        CALL COUNTDOWN     ;显示倒计时54321

        MOV DX,OFFSET STR2   ; 显示TIME'S UP!
        MOV AH,9
        INT 21H

        MOV AH,4CH
        INT 21H

;延时显示倒计时数字子程序
COUNTDOWN PROC
    A1: MOV AH,02H
        INT 21H         ;功能调用

        PUSH DX         ;因为下一步会用到DL寄存器,所以此时的子程序的DL要提前压入堆栈区保护起来。堆栈操作以字为单位,所以要压入DX。
        MOV DL,20H      ;空格的ASCII码值为20H
        MOV AH,02H
        INT 21H
        POP DX

        PUSH CX         ;因为下一步调用的子延时程序DT1S中会用到CX和DX寄存器,所以此子程序的CX和DX要提前压入堆栈区保护起来。
        PUSH DX

        MOV AL,	1	;延时1秒
        CALL DT1S	;调用延时1S子程序

        POP DX          ;恢复压入堆栈区的CX和DX的值
        POP CX

        DEC DL          ;切换下一个字母

        LOOP A1
        RET
COUNTDOWN ENDP


;延时1S子程序
DT1S PROC               ;使用的工作寄存器为:CX、DX,入口参数为AL寄存器,AL的数值为需要延时的秒数。
    D0: MOV CX,	1000    ;内循环延时约1ms,外循环为1000次,则内外循环一轮为1秒。
    D1: MOV DX,	N1MS	;建立延时1ms系数循环计数次数
    D2:	DEC DX
	JNZ D2
	DEC CX
	JNZ D1
	DEC AL
	JNZ D0
	RET
DT1S ENDP

CODE ENDS
      END START

3.编程统计AX寄存器中1的个数,并将结果存入SUM单元。

思路:将AX寄存器的各位依次移入CF标志位,通过检测CF的值来判断该位是否为1,依此统计AX所含1的个数。可以利用计数办法总共检测16次,还可以通过判断移位后二进制数是否变为0作为循环结束的条件。当二进制数的后几位全部为0时,可以提前结束循环,提高程序运行效率。 

  • 使用SHL指令来向左移动,使用AND/OR指令来判断AX中的内容是否为0
  • 在使用2号输出功能的时候,mov的DL的值必须是ASCII码或者一个特定字符才行,比如输出SUM变量中存储的数字,需要把SUM变量中数字的ASCII码值传给DL,而不能直接MOV DL,SUM
  • 要想在屏幕输出的话,源操作数必须是阿斯克码或者是字符

程序段: 

MOV  BL, 0       ;计数单元BL清零
AGAIN: OR AX, AX       ;测试AX是否为0,也可以用AND指令
       JZ  EXIT          ;若AX=0,则转移到结束点
       SHL  AX, 1       ;若AX不为0,则将AX最高位移动到CF
       JNC  NEXT         ;如果CF=0,则转去AGAIN继续
       INC  BL           ;如果CF不为0,则BL加1
NEXT:  JMP  AGAIN
EXIT: MOV  SUM, BL

 完整代码段:定义AX的值,最后输出SUM的值

;编程统计AX寄存器中1的个数,并将结果存入SUM单元,输出SUM的个数
DATA SEGMENT
     D1 DW 000FH
     SUM DB 0
DATA ENDS

CODE SEGMENT
    ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
    MOV DS,AX
    MOV BL,0
    MOV AX,D1
FOR:AND AX,AX
    JZ EXIT
    SHL AX,1
    JNC BB
    INC BL
BB:JMP FOR
    
EXIT:MOV SUM,BL;移进SUM单元

MOV DL,SUM;输出准备,移进DL

CMP DL,0AH;判断是数字还是字母
JNC LETTER
JMP NUMBER

LETTER:SUB DL,09H
       ADD DL,40H
       JMP OUTPUT
       
NUMBER:ADD DL,30H

OUTPUT:MOV AH,2
       INT 21H

MOV AH,4CH
INT 21H

CODE ENDS
END START

  • 13
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值