Assembly 8086技术咨询:不使用DOS中断如何获取时间?
在8086汇编中不借助DOS中断获取系统时间的方法
要在8086汇编环境中不依赖DOS中断获取系统时间,核心是使用BIOS中断0x1A——这是实模式下直接与系统硬件交互的底层接口,无需DOS支持。下面介绍两种常用的实现方式:
1. 直接获取BCD格式的时分秒(推荐)
BIOS中断0x1A的02h功能可以直接返回格式化的时间数据,以BCD码(二进制编码十进制)存储,无需额外计算,转换更高效:
用法说明
- 调用前设置
AH = 02h - 执行
INT 1Ah后,寄存器返回值:CH:小时(BCD码,范围00-23)CL:分钟(BCD码,范围00-59)DH:秒(BCD码,范围00-59)DL:世纪(BCD码,部分BIOS支持,如19代表19xx年)CF标志:若BIOS不支持该功能则置位
代码示例
; MASM/TASM 风格代码 .MODEL SMALL .STACK 100h .DATA HourMsg DB 'Hour: $' MinMsg DB 0Dh, 0Ah, 'Minute: $' SecMsg DB 0Dh, 0Ah, 'Second: $' .CODE MAIN PROC MOV AX, @DATA MOV DS, AX ; 调用BIOS中断获取时间(核心,未依赖DOS) MOV AH, 02h INT 1Ah ; 显示小时(BCD转ASCII后打印,此处DOS中断仅用于输出) LEA DX, HourMsg MOV AH, 09h INT 21h MOV AL, CH CALL BCD_TO_ASCII ; 显示分钟 LEA DX, MinMsg MOV AH, 09h INT 21h MOV AL, CL CALL BCD_TO_ASCII ; 显示秒 LEA DX, SecMsg MOV AH, 09h INT 21h MOV AL, DH CALL BCD_TO_ASCII ; 程序退出 MOV AH, 4Ch INT 21h MAIN ENDP ; BCD转ASCII并打印两位数字 BCD_TO_ASCII PROC PUSH BX MOV BL, AL ; 处理十位 SHR AL, 4 ADD AL, 30h MOV DL, AL MOV AH, 02h INT 21h ; 处理个位 MOV AL, BL AND AL, 0Fh ADD AL, 30h MOV DL, AL MOV AH, 02h INT 21h POP BX RET BCD_TO_ASCII ENDP END MAIN
2. 通过系统滴答数计算时间
如果BIOS不支持02h功能,可以使用00h功能获取从午夜开始的系统滴答数(每秒约18.2次滴答),再手动换算为时分秒:
用法说明
- 调用前设置
AH = 00h - 执行
INT 1Ah后,寄存器返回值:CX:DX:从午夜开始的总滴答数AL:午夜后滴答计数器溢出次数(超过24小时时递增)
- 换算逻辑:总秒数 = 总滴答数 ÷ 18.2,再将总秒数拆分为小时、分钟、秒
代码示例
; 计算总秒数并拆分为时分秒 MOV AH, 00h INT 1Ah ; 组合CX:DX为64位总滴答数 MOV AX, CX MOV BX, 1000h MUL BX ; AX = CX * 65536,DX:AX = CX*65536 ADD AX, DX ADC DX, 0 ; DX:AX = 总滴答数 ; 转换为总秒数(近似用18代替18.2,需精确可调整除数) MOV BX, 18 DIV BX ; AX = 总秒数,DX = 余数 ; 拆分总秒数为小时、分钟、秒 MOV BX, 3600 DIV BX ; AX = 小时,DX = 剩余秒数 MOV [Hour], AX MOV AX, DX MOV BX, 60 DIV BX ; AX = 分钟,DX = 秒数 MOV [Minute], AX MOV [Second], DX ; 定义存储变量 Hour DW ? Minute DW ? Second DW ?
注意事项
- BIOS中断0x1A属于实模式接口,可在引导扇区、纯实模式程序中直接使用,完全不依赖DOS
- BCD码转换:BCD的每4位对应一个十进制数字,例如
0x15表示十进制15,转换为二进制需计算1*10 +5=15 - 若需获取日期,可使用BIOS中断0x1A的
04h功能,同样不依赖DOS
内容的提问来源于stack exchange,提问作者Nek It
相关产品推荐
相关产品推荐

