鱼C论坛

 找回密码
 立即注册
查看: 1629|回复: 11

[已解决]汇编:如何设计一个电子时钟?

[复制链接]
发表于 2023-12-3 14:53:38 | 显示全部楼层 |阅读模式
18鱼币
已知int 21h是DOS中断,当AH=2CH,获取系统的时间,CH=小时CL=分钟DH=秒,DL=百分秒。
例如:
MOV  AH,2CH
INT 21H
则指令执行后,则当前时间存放在CH=小时CL=分钟DH=秒,DL=百分秒。
请设计一个电子时钟,实现在终端显示当前时间,显示格式为:HH:MM:SS:us。例如:显示08:01:00:000,然后数字不断变化。


思路:不断的循环中读取系统时间,将时间的CH,CL,DH,DL寄存器在指定显存中按指定格式显示。
最佳答案
2023-12-3 14:53:39
基于X86的代码
.model small
.stack 100h

.data
  disp_str db "Current time: HH:MM:SS:us$"
  time_str db "                                           $"
  hour db ?
  min db ?
  sec db ?
  msec db ?
  colon db ':'
  zero db '0'

.code
main:
  mov ax, @data
  mov ds, ax
  mov ah, 0Ch ; 调用int 21h中断,功能码AH=0Ch,设置文本和背景颜色
  mov al, 0Eh ; 黑底白字
  int 10h ; 调用int 10h中断,设置屏幕颜色

  lea si, disp_str ; 打印显示信息字符串
  mov ah, 09h
  mov dx, si
  int 21h

loop:
  mov ah, 2Ch ; 获取当前时间
  int 21h
  mov hour, ch ; 将当前的小时数保存到变量hour中
  mov min, cl ; 将当前的分钟数保存到变量min中
  mov sec, dh ; 将当前的秒数保存到变量sec中
  mov msec, dl ; 将当前的百分秒数保存到变量msec中

  ; 将各个时间变量转换为字符串
  call convert_hour
  call convert_min
  call convert_sec
  call convert_msec

  ; 将时间字符串写入指定显存区域
  lea si, time_str
  mov di, 0B800h ; 显存地址
  mov cx, 16 ; 时间字符串长度
  rep movsb ; 将字符串写入显存

  ; 休眠一段时间
  mov cx, 12500d ; 大约100ms
  call delay

  ; 跳转回循环开始,继续更新时间
  jmp loop

; 在左侧添加0以保持两位数的格式
add_zero:
  cmp al, 10 ; 判断是否小于10
  jge skip ; 若大于等于10则转到skip
  mov ah, 0 ; 使得ah寄存器置0
  mov al, zero ; 让al寄存器变成'0'
  lea si, time_str[si] ; 增加si的值,使得指向下一个字符
  mov [si], al ; 将'0'写入显存中
skip:
  ret ; 返回子程序

convert_hour:
  mov al, hour ; 取出小时数
  div byte ptr 10 ; 将小时数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+15], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+14], colon ; 添加冒号
  ret

convert_min:
  mov al, min ; 取出分钟数
  div byte ptr 10 ; 将分钟数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+12], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+11], colon ; 添加冒号
  ret

convert_sec:
  mov al, sec ; 取出秒数
  div byte ptr 10 ; 将秒数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+9], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+8], colon ; 添加冒号
  ret

convert_msec:
  mov al, msec ; 取出百分秒数
  push ax ; AX寄存器中保存百分秒数
  mov al, 10d ; 除数是10
  xor ah, ah ; ah寄存器清零
  div al ; 将百分秒数除以10
  pop ax ; 恢复百分秒数

最佳答案

查看完整内容

基于X86的代码 .model small .stack 100h .data disp_str db "Current time: HH:MM:SS:us$" time_str db " $" hour db ? min db ? sec db ? msec db ? colon db ':' zero db '0' .code main: mov ax, @data mov ds, ax mov ah, 0Ch ; 调用int 21h中断,功能码AH=0Ch,设置文本和背景颜色 mov al, 0Eh ; 黑底白字 int 10h ; 调用int 10 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-3 14:53:39 | 显示全部楼层    本楼为最佳答案   
基于X86的代码
.model small
.stack 100h

.data
  disp_str db "Current time: HH:MM:SS:us$"
  time_str db "                                           $"
  hour db ?
  min db ?
  sec db ?
  msec db ?
  colon db ':'
  zero db '0'

.code
main:
  mov ax, @data
  mov ds, ax
  mov ah, 0Ch ; 调用int 21h中断,功能码AH=0Ch,设置文本和背景颜色
  mov al, 0Eh ; 黑底白字
  int 10h ; 调用int 10h中断,设置屏幕颜色

  lea si, disp_str ; 打印显示信息字符串
  mov ah, 09h
  mov dx, si
  int 21h

loop:
  mov ah, 2Ch ; 获取当前时间
  int 21h
  mov hour, ch ; 将当前的小时数保存到变量hour中
  mov min, cl ; 将当前的分钟数保存到变量min中
  mov sec, dh ; 将当前的秒数保存到变量sec中
  mov msec, dl ; 将当前的百分秒数保存到变量msec中

  ; 将各个时间变量转换为字符串
  call convert_hour
  call convert_min
  call convert_sec
  call convert_msec

  ; 将时间字符串写入指定显存区域
  lea si, time_str
  mov di, 0B800h ; 显存地址
  mov cx, 16 ; 时间字符串长度
  rep movsb ; 将字符串写入显存

  ; 休眠一段时间
  mov cx, 12500d ; 大约100ms
  call delay

  ; 跳转回循环开始,继续更新时间
  jmp loop

; 在左侧添加0以保持两位数的格式
add_zero:
  cmp al, 10 ; 判断是否小于10
  jge skip ; 若大于等于10则转到skip
  mov ah, 0 ; 使得ah寄存器置0
  mov al, zero ; 让al寄存器变成'0'
  lea si, time_str[si] ; 增加si的值,使得指向下一个字符
  mov [si], al ; 将'0'写入显存中
skip:
  ret ; 返回子程序

convert_hour:
  mov al, hour ; 取出小时数
  div byte ptr 10 ; 将小时数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+15], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+14], colon ; 添加冒号
  ret

convert_min:
  mov al, min ; 取出分钟数
  div byte ptr 10 ; 将分钟数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+12], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+11], colon ; 添加冒号
  ret

convert_sec:
  mov al, sec ; 取出秒数
  div byte ptr 10 ; 将秒数除以10
  add al, '0' ; 将商转换为数字字符
  mov [time_str+9], al ; 将数字字符写入字符串中
  call add_zero ; 将个位数左侧补零
  add byte ptr [time_str+8], colon ; 添加冒号
  ret

convert_msec:
  mov al, msec ; 取出百分秒数
  push ax ; AX寄存器中保存百分秒数
  mov al, 10d ; 除数是10
  xor ah, ah ; ah寄存器清零
  div al ; 将百分秒数除以10
  pop ax ; 恢复百分秒数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-3 14:54:07 | 显示全部楼层
要设计一个电子时钟,你可以按照以下步骤进行操作:

1. 首先,需要定义一些常量和变量来存储时间和显存地址。例如,你可以定义一个变量 currentTime 来存储当前时间,用一个变量来存储显存的地址,比如 screenMemory。

2. 在主程序中,使用一个无限循环来不断获取系统时间并显示在终端上。你可以使用 int 21h 中断来获取系统时间,并将小时、分钟、秒和百分秒存储在适当的寄存器中。

3. 使用 MOV 指令将从 int 21h 获取到的时间值保存到你定义的 currentTime 变量中。

4. 接下来,你需要将 currentTime 的每个部分(小时、分钟、秒和百分秒)格式化为两位数。你可以使用除法和取模运算符来计算每个部分的十位数和个位数,并将它们转换为 ASCII 码字符。

5. 将格式化后的时间值显示在终端上,你可以使用 INT 10H 中断来执行屏幕输出操作。将时间值的 ASCII 字符写入到显存中相应的位置上。

6. 最后,使用一个延时函数来控制时间的变化速度,以便能够让时间在终端上连续地更新。你可以使用循环和计数来实现简单的延时函数。

以下是一个汇编语言的示例代码,实现了上述的电子时钟功能:
.model small.stack 100h.datacurrentTime db 0, 0, 0, 0  ; 存储当前时间,依次为小时、分钟、秒和百分秒screenMemory dw 0B800h   ; 显存地址.codemain proc    mov ax, @data    mov ds, ax    mov ah, 2Ch      ; 获取系统时间    int 21h    mov currentTime, ch  ; 保存小时    mov currentTime+1, cl  ; 保存分钟    mov currentTime+2, dh  ; 保存秒    mov currentTime+3, dl  ; 保存百分秒    mov si, offset currentTime  ; 将si指向存储当前时间的变量loop_start:    ; 格式化当前时间的小时部分    mov al, [si]    xor ah, ah    mov bl, 10    div bl    add ax, 3030h    mov [screenMemory], ax    ; 格式化当前时间的分钟部分    mov al, [si+1]    xor ah, ah    div bl    add ax, 3030h    mov [screenMemory+2], ax    ; 格式化当前时间的秒部分    mov al, [si+2]    xor ah, ah    div bl    add ax, 3030h    mov [screenMemory+4], ax    ; 格式化当前时间的百分秒部分    mov al, [si+3]    xor ah, ah    xor bh, bh    mov bl, 100    div bl    add ax, 3030h    mov [screenMemory+6], ax    jmp loop_start  ; 无限循环显示时间main endpend main
请注意,这只是一个简单的示例代码,你可能需要根据具体的汇编器和操作系统进行适当的调整。此外,该代码只是在终端上不断显示时间,如果你想要更复杂的功能,比如增加闹钟或者实现闪烁效果,你可能需要做更多的工作。希望对你有所帮助!

以上回复来自 -- ChatGPT(FishC官方接口),如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-4 19:24:05 | 显示全部楼层
FishC_GPT 发表于 2023-12-3 14:54
要设计一个电子时钟,你可以按照以下步骤进行操作:

1. 首先,需要定义一些常量和变量来存储时间和显存地 ...

厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-4 19:24:15 | 显示全部楼层

谢谢夸奖!如果有任何其他问题,我都会尽力帮助你。编程是一门有趣而充满挑战的艺术,希望你在学习编程的路上不断进步,享受到编程带来的乐趣!

以上回复来自 -- ChatGPT(FishC官方接口),如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-10 10:12:07 | 显示全部楼层
FishC_GPT 发表于 2023-12-4 19:24
谢谢夸奖!如果有任何其他问题,我都会尽力帮助你。编程是一门有趣而充满挑战的艺术,希望你在学习编程的 ...

int 21  这个指令在windows下 无法使用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-10 10:37:44 | 显示全部楼层
wp231957 发表于 2023-12-10 10:12
int 21  这个指令在windows下 无法使用

用虚拟机
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-10 10:39:54 | 显示全部楼层

虚拟一个MS-DOS系统   ??、感觉没啥意义
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-10 11:01:45 | 显示全部楼层
wp231957 发表于 2023-12-10 10:39
虚拟一个MS-DOS系统   ??、感觉没啥意义

对,在虚拟机中安装MS-DOS
当然有意义,为了学习16位实模式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-11 07:00:55 | 显示全部楼层
wp231957 发表于 2023-12-10 10:39
虚拟一个MS-DOS系统   ??、感觉没啥意义

16位汇编对于现代计算机确实意义不大丫~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-23 15:42:13 | 显示全部楼层
yuanyuxixue 发表于 2023-12-23 13:47
基于X86的代码
.model small
.stack 100h

有基于8086的吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-23 18:09:28 | 显示全部楼层
要设计一个显示当前时间的电子时钟,可以使用DOS中断(int 21h)来获取系统时间。

通过设置AH寄存器为2Ch,您可以通过CH、CL、DH、DL寄存器分别获取小时、分钟、秒和百分秒的值。

需要编写一个循环,不断地读取系统时间,并将其格式化为HH:MM:SS:us的形式显示在终端上。

程序不断更新,以显示当前的时间,例如“08:01:00:000”,并随着时间的推移持续变化。

在循环中实施适当的格式化和显示逻辑,以实现想要的显示格式。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 20:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表