汇编开发求助:无法正确打印系统计时器寄存器的8位数值
如何正确打印DOS系统计时器返回的8位日期数值
问题根源分析
你的代码里8位数值打印错误的核心原因是误用了16位除法指令:
div si是16位除法操作,会把AX寄存器整体作为被除数,但你只给AL或AH赋值了目标8位数值,另一个8位寄存器里残留着之前程序运行的垃圾值,导致被除数远大于实际要打印的数值,最终输出异常。- 比如
print_number8bith中,你把月份(DH)放到AH,但AL还是之前打印年份时残留的值,此时AX是一个随机的16位数,除以10后自然得到错误结果。
修正方案
只需要写一个通用的8位数值打印函数,使用8位除法指令来处理,避免16位寄存器的干扰:
- 把要打印的8位数值放到
AL寄存器 - 用
div bl(8位除法)来做十进制拆分,拆分前先清零AH(避免余数干扰) - 把余数转成ASCII后入栈,最后依次弹出打印
修正后的完整代码
SSEG segment stack db 256 dup(0) SSEG ends DSEG segment whitespace db ' $' DSEG ends CSEG segment assume cs:CSEG,ds:DSEG,ss:SSEG begin: mov ax, DSEG mov ds, ax ; 调用DOS中断2Ah获取系统日期 mov ah, 2Ah int 21h ; 打印年份(CX寄存器,16位) mov bx, cx call print_number16bit ; 打印月份(DH寄存器,8位) mov al, dh call print_number8bit ; 打印日期(DL寄存器,8位) mov al, dl call print_number8bit ; 打印星期(AL寄存器,8位,中断返回后直接可用) call print_number8bit ; 等待按键 mov ah,01h int 21h ; 程序退出 mov ah,4ch int 21h ; 打印16位数值(参数:BX寄存器存要打印的数值) print_number16bit proc mov si,10 mov ax,bx mov cx,0 a1: mov dx,0 div si add dx,'0' push dx inc cx cmp ax,0 jnz a1 aa1: pop dx mov ah,02h int 21h loop aa1 mov ah, 09h mov dx, offset whitespace int 21h ret endp ; 打印8位数值(参数:AL寄存器存要打印的数值) print_number8bit proc mov bl, 10 ; 除数设为10 mov cx, 0 a2: xor ah, ah ; 清零AH,确保8位除法的被除数只有AL里的数值 div bl ; AL = 商,AH = 余数 add ah, '0' ; 余数转ASCII字符 push ax ; 将余数(存在AH)入栈保存 inc cx cmp al, 0 jnz a2 aa2: pop ax mov dl, ah ; 取出栈中的余数 mov ah, 02h int 21h loop aa2 ; 打印分隔空格 mov ah, 09h mov dx, offset whitespace int 21h ret endp CSEG ends end begin
关键修改说明
- 合并了原来的
print_number8bitl和print_number8bith为一个通用的print_number8bit函数,减少冗余代码 - 使用
div bl(8位除法)替代div si,仅用AL作为被除数,提前清零AH避免干扰 - 主程序中直接把8位寄存器(DH、DL、AL)的值放到
AL后调用函数,参数传递更清晰
内容的提问来源于stack exchange,提问作者Coder4Fun250
相关产品推荐
相关产品推荐

