微机原理程序编写及调试

用汇编语言设计体育比赛计时程序,程序运行,屏幕显示00:00:00,并开始按秒计时。每按下一次空格键,在下一行显示当前暂停的时刻,最多可计10次暂停时间。按下Q键,程序结束。用dos对程序进行调试。

img

汇编

基于new bing的编写参考:

.model small
.stack 100h
.data
    time db 0, 0, 0, '$'  ; 存储时间的变量
    pause_times db 10     ; 剩余可暂停次数
.code
start:
    mov ax, @data        ; 初始化数据段寄存器
    mov ds, ax
    mov ah, 0            ; 按键输入函数号
    int 16h              ; 等待用户按下键盘按键
    cmp ah, 20h          ; 如果按下的是空格键
    je pause_time        ; 跳转到暂停计时处理
    cmp ah, 10h          ; 如果按下的是Q键
    je end_program       ; 跳转到程序结束处理
    jmp start            ; 继续等待用户按键

pause_time:
    cmp pause_times, 0   ; 如果剩余可暂停次数为0
    je start             ; 返回继续等待用户按键
    dec pause_times      ; 剩余可暂停次数减1
    mov ah, 0            ; 获取当前时刻的函数号
    int 1Ah              ; 获取当前时刻,存储在CX:DX中
    mov bx, offset time  ; 将时间变量的地址存储在BX中
    mov [bx], dl         ; 将秒存储在time[0]
    mov [bx+1], dh       ; 将分存储在time[1]
    mov [bx+2], ch       ; 将时存储在time[2]
    add bx, 3            ; 偏移3字节,指向字符串结束符
    mov byte ptr [bx], '$' ; 在字符串结束处添加结束符
    mov ah, 9            ; 显示字符串函数号
    mov dx, offset time  ; 将时间变量的地址存储在DX中
    int 21h              ; 显示时间字符串
    jmp start            ; 返回继续等待用户按键

end_program:
    mov ah, 4Ch          ; 程序结束函数号
    mov al, 0            ; 返回值为0
    int 21h
end start


这个程序使用BIOS中断来读取键盘输入和获取系统时间,并使用DOS中断来在屏幕上显示信息。在程序开始时,在屏幕左上角显示"00:00:00",然后等待用户按下空格键或Q键。如果按下空格键,程序会将此时的时间显示在屏幕下方,并将剩余可暂停次数减1;如果按下Q键,程序会直接结束。程序最多可以暂停10次。

请注意,由于不同的汇编语言实现有所不同,这份代码可能需要根据具体情况进行适当修改才能运行。

可以参考下

;交通灯源码
MY_STACK    SEGMENT PARA 'STACK'
DB    100 DUP(?)
MY_STACK    ENDS
 
MY_DATA    SEGMENT PARA 'DATA'
IO_9054base_address DB 4 DUP(0)    ;PCI 卡 9054 芯片 I/O 基地址暂存空间
IO_base_address    DB 4 DUP(0)    ;PCI 卡 I/O 基地址暂存空间
pcicardnotfind    DB 0DH,0AH,'pci card not find or address/interrupt error !!!',0DH,0AH,'$'
GOOD    DB 0DH,0AH,'The Program is Executing !',0DH,0AH,'$'
 
P8255_A     DW    0000H
P8255_B     DW    0001H
P8255_C     DW    0002H
P8255_MODE DW 0003H DELAY_SET EQU 5fffH DELAY_SET1  EQU    18ffH
 
MES2    DB '    PCI CONFIG READ ERROR!    $' MY_DATA        ENDs
MY_CODE    SEGMENT PARA 'CODE'
 
MY_PROC    PROC    FAR
ASSUME  CS:MY_CODE, DS:MY_DATA, SS:MY_STACK
 
START:
.386   ;386 模式编译
MOV    AX,MY_DATA
MOV    DS,AX
MOV    ES,AX
 
MOV    AX,MY_STACK
MOV    SS,AX
CALL    FINDPCI    ;自动查找 PCI 卡资源及 IO 口基址
 
;    MOV
MOV    CX,word ptr IO_base_address
CX,0E800H    ;直接加入(E800:本机 PCI 卡 IO 口基址)
    ADD    P8255_A,CX    ;PCI 卡 IO 基址+偏移
    ADD    P8255_B,CX
    ADD    P8255_C,CX
    ADD    P8255_MODE,CX
    MOV MOV    DX,P8255_MODE
AL,80H    ;3 个口全部为输出
    OUT    DX,AL
    MOV    DX,P8255_A
    CALL    ST0    ;全为红灯
TRAFFIC1:    CALL
CALL    ST1
ST5    ;南北为绿灯,东西为红灯
    CALL    ST2    ;南北红灯闪烁,东西为红灯
    CALL    ST3
CALL    ST6    ;南北为红灯,东西为绿灯
    CALL    ST4    ;南北为红灯,东西黄灯闪烁
    CALL    BREAK
    JMP    TRAFFIC1
MY_PROC    ENDp    
ST0    PROC    NEAR
    MOV    AL,1BH
    OUT    DX,AL
    CALL    DELAY
    RET    
ST0    ENDp    
ST1    PROC    NEAR
    MOV    DX,P8255_A
    MOV    AL,0EDH
    OUT    DX,AL
    CALL    DELAY
    CALL    DELAY
    CALL    DELAY
    RET    
ST1    ENDp    
ST5    PROC    NEAR
    MOV    DX,P8255_A
    MOV    AL,0EBH
    OUT    DX,AL
    CALL    DELAY
    RET    
ST5    ENDp    
ST2    PROC    NEAR
    MOV    CX,5H
ST20:    MOV    AL,0EBH
    OUT    DX,AL
    CALL    DELAY1
    MOV    AL,0EFH
    OUT    DX,Al
    CALL    DELAY1
    LOOP    ST20
    RET    
ST2    ENDp    
ST3    PROC    NEAR
    MOV    AL,0DEH
    OUT    DX,AL
    CALL    DELAY
    CALL    DELAY
    CALL    DELAY
    RET    
ST3    ENDp    
ST6    PROC    NEAR
    MOV    DX,P8255_A
    MOV    AL,0BEH
 
 
    OUT    DX,AL
    CALL    DELAY
    RET    
ST6    ENDp    
ST4    PROC    NEAR
    MOV    CX,5H
ST40:    MOV    AL,0BEH
    OUT    DX,AL
    CALL    DELAY1
    MOV    AL,0FEH
    OUT    DX,AL
    CALL    DELAY1
    LOOP    ST40
    RET    
ST4    ENDp    
;
;*****************************************************************************
;    /* 延时子程序 */
;*****************************************************************************
;
DELAY    PROC    NEAR    ;延时程序
PUSHF PUSH    DX
PUSH    CX
MOV    DX,DELAY_SET
D1:    MOV    CX,-1
D2:    DEC    CX
JNZ    D2
DEC    DX
JNZ    D1
POP    CX
POP    DX POPF
RET
DELAY    ENDp
DELAY1    PROC    NEAR    ;延时程序
PUSHF PUSH    DX
PUSH    CX
MOV    DX,DELAY_SET1
D3:    MOV    CX,-1
D4:    DEC    CX
JNZ    D4
DEC    DX
JNZ    D3
POP    CX
POP    DX POPF
RET
DELAY1    ENDp
;
;*****************************************************************************
;    /* 按任意键退出子程序 */
;*****************************************************************************
;
BREAK    PROC    NEAR    ;按任意键退出
PUSHF PUSH    AX
PUSH    DX
MOV    AH,06H
MOV    DL,0FFH
INT    21H
JE    RETURN
MOV    AX,4C00H
INT    21H
RETURN:    POP    DX
POP    AX POPF
RET
BREAK    ENDP
;
;*****************************************************************************
;    /* 找卡子程序 */
 
;*****************************************************************************
;
;FUNCTION CODE
IO_port_addre    EQU 0CF8H    ;32 位配置地址端口
IO_port_data    EQU 0CFCH    ;32 位配置数据端口
IO_PLX_ID    EQU 200810B5H    ;PCI 卡设备及厂商 ID
BADR0    =    10H    ;基地址寄存器 0
BADR1    =    14H    ;基地址寄存器 1
BADR2    =    18H    ;基地址寄存器 2
BADR3    =    1CH    ;基地址寄存器 3
FINDPCI    PROC    NEAR    ;查找 PCI 卡资源并显示
PUSHAD PUSHFD
MOV    EBX,080000000H
FINDPCI_next:
ADD    EBX,100H
CMP    EBX,081000000H
JNZ    findpci_continue
MOV    DX,offset pcicardnotfind    ;显示未找到 PCI 卡提示信息
MOV    AH,09H
INT    21H
MOV    AH,4CH
INT    21H    ;退出
findpci_continue:
MOV
MOV    DX,IO_port_addre
EAX,EBX    
OUT    DX,EAX    ;写地址口
MOV    DX,IO_port_data    
IN    EAX,DX    ;读数据口
CMP    EAX,IO_PLX_ID    
JNZ    findpci_next    ;检查是否发现 PCI 卡
MOV    DX,IO_port_addre    
MOV    EAX,EBX    
ADD
OUT    EAX,BADR1
DX,EAX    ;写地址口
MOV    DX,IO_port_data    
IN    EAX,DX    ;读数据口
MOV    dword ptr IO_9054base_address,EAX    
AND    EAX,1    
JZ    findPCI_next    ;检查是否为 i/o 基址信息
MOV    EAX,dword ptr IO_9054base_address    
AND    EAX,0fffffffeh    
MOV    dword ptr IO_9054base_address,EAX    ;去除 i/o 指示位并保存
MOV    DX,IO_port_addre    
MOV    EAX,EBX    
ADD    EAX,BADR2    
OUT    DX,EAX    ;写地址口
MOV
IN    DX,IO_port_data
EAX,DX    ;读数据口
MOV    dword ptr IO_base_address,EAX    
AND
JZ    EAX,1
findPCI_next    ;检查是否为 i/o 基址信息
MOV    EAX,dword ptr IO_base_address    
AND
MOV    EAX,0fffffffeh
dword ptr IO_base_address,EAX    ;去除 i/o 指示位并保存
    MOV    DX,offset good    ;显示开始执行程序信息
    MOV    AH,09H
    INT    21H
    POPfd    
    POPad    
    RET    
findPCI    ENDP    
MY_CODE    ENDS    
END START
;I/O 实验源码
DATA    SEGMENT DELAY_SET    EQU    0FFFH L_TO_R DB ?
R_TO_L DB ?
 
DATA    ENDs
 
CODE    SEGMENT
ASSUME DS : DATA, CS : CODE START:
MOV AX, DATA
MOV DS, AX
MOV L_TO_R, 07FH MOV R_TO_L, 0FEH MOV DX, 0ec03h MOV AL, 89h
OUT  DX, AL
X:
MOV DX, 0ec02h IN  AL,  DX  CMP AL, 0h
JE FLOW_1 CMP AL, 00fh JE FLOW_2
MOV DX, 0ec00h OUT DX, AL CALL  DELAY  JMP START
 
FLOW_1:
MOV AL, L_TO_R MOV AH, R_TO_L ROR AL, 1
MOV L_TO_R, AL ROL AH, 1
MOV R_TO_L, AH JMP SHOW_1
 
FLOW_2:
MOV AL, R_TO_L MOV AH, L_TO_R ROR AL, 1
MOV L_TO_R, AL ROL AH, 1
MOV R_TO_L, AH JMP SHOW_2
 
SHOW_1:
MOV DX, 0ec00h OUT  DX, AL  MOV  AL, AH  MOV DX, 0ec01h OUT DX, AL CALL  DELAY  JMP X
 
SHOW_2:
MOV DX, 0ec01h OUT  DX, AL  MOV  AL, AH  MOV DX, 0ec00h OUT DX, AL CALL  DELAY  JMP X
 
DELAY    PROC    NEAR
    PUSHF    
    PUSH    DX
    PUSH    CX
    MOV    DX,DELAY_SET
D1:    MOV    CX,-1
D2:    DEC    CX
    JNZ    D2
    DEC    DX
    JNZ    D1
    POP    CX
    POP    DX
    POPF    
    RET    
DELAY    ENDp
 
CODE    ENDs END START
 
 
;流水灯源码
MY_STACK    SEGMENT PARA 'STACK'
DB    100 DUP(?)
MY_STACK    ENDS
 
MY_DATA    SEGMENT PARA 'DATA'
IO_9054base_address DB 4 DUP(0)    ;PCI 卡 9054 芯片 I/O 基地址暂存空间
IO_base_address    DB 4 DUP(0)    ;PCI 卡 I/O 基地址暂存空间
pcicardnotfind    DB 0DH,0AH,'pci card not find or address/interrupt error !!!',0DH,0AH,'$'
GOOD    DB 0DH,0AH,'The Program is Executing !',0DH,0AH,'$'
LA    DB    ?
LB    DB    ?
P8255_A    DW    0000H
P8255_B    DW    0001H
P8255_C    DW    0002H
P8255_MODE DW    0003H DELAY_SET    EQU    11FFH
MES2    DB '    PCI CONFIG READ ERROR!    $' MY_DATA    ENDs
MY_CODE    SEGMENT PARA 'CODE' MY_PROC    PROC    FAR
ASSUME  CS:MY_CODE, DS:MY_DATA, SS:MY_STACK
 
START:
.386    ;386 模式编译
MOV    AX,MY_DATA
MOV    DS,AX
MOV    ES,AX
MOV    AX,MY_STACK
MOV    SS,AX
CALL    FINDPCI    ;自动查找 PCI 卡资源及 IO 口基址
    MOV
ADD    CX,word ptr IO_base_address
P8255_A,CX    ;PCI 卡 IO 基址+偏移
    ADD    P8255_B,CX
    ADD    P8255_C,CX
    ADD    P8255_MODE,CX
    MOV    DX,P8255_MODE    ;8255 初始化,三个口全为输出
    MOV    AL,80H
    OUT    DX,AL
    MOV    DX,P8255_A    ;PA 口赋初值
    MOV    AL,7FH
    OUT    DX,AL
    MOV    LA,AL
    MOV    DX,P8255_B    ;PB 口赋初值
    MOV    AL,0FEH
    OUT    DX,AL
    MOV    LB,AL
    CALL    DELAY
A1:    MOV    AL,LA    ;PA 口数据右移一位
    ROL    AL,1
    MOV    LA,AL
    MOV    DX,P8255_A
    OUT    DX,AL
    MOV    AL,LB
    ROR    AL,1
    MOV    LB,AL
    MOV    DX,P8255_B    ;PB 口数据右移一位
    OUT    DX,AL
    CALL    DELAY    ;延时
    CALL    BREAK    ;按任意键退出
    JMP    A1
MY_PROC    ENDp    
DELAY    PROC    NEAR    ;延时程序
    PUSHF    
    PUSH    DX
 
 
 
 
D1:    PUSH MOV MOV    CX DX,DELAY_SET CX,-1
D2:
 
 
 
 
 
 
DELAY    DEC
JNZ DEC JNZ POP POP POPF RET ENDp    CX
D2 DX D1 CX DX
BREAK
 
 
 
 
 
RETURN:    PROC MOV MOV INT JE MOV INT RET    NEAR AH,06H DL,0FFH 21H RETURN AX,4C00H 21H
BREAK    ENDP    
;*****************************************************************************
;    /* 找卡子程序 */
;*****************************************************************************
IO_port_addre    EQU 0CF8H    ;32 位配置地址端口
IO_port_data    EQU 0CFCH    ;32 位配置数据端口
IO_PLX_ID    EQU 200810B5H    ;PCI 卡设备及厂商 ID
BADR0    =    10H    ;基地址寄存器 0
BADR1    =    14H    ;基地址寄存器 1
BADR2    =    18H    ;基地址寄存器 2
BADR3    =    1CH    ;基地址寄存器 3
FINDPCI    PROC    NEAR    ;查找 PCI 卡资源并显示
PUSHAD PUSHFD
MOV    EBX,080000000H
FINDPCI_next:
ADD    EBX,100H
CMP    EBX,081000000H
JNZ    findpci_continue
MOV    DX,offset pcicardnotfind    ;显示未找到 PCI 卡提示信息
MOV    AH,09H
INT    21H
MOV    AH,4CH
INT    21H    ;退出
findpci_continue:
MOV
MOV    DX,IO_port_addre
EAX,EBX    
OUT    DX,EAX    ;写地址口
MOV    DX,IO_port_data    
IN    EAX,DX    ;读数据口
CMP
JNZ    EAX,IO_PLX_ID
findpci_next    ;检查是否发现 PCI 卡
MOV    DX,IO_port_addre    
MOV    EAX,EBX    
ADD    EAX,BADR1    
OUT    DX,EAX    ;写地址口
MOV    DX,IO_port_data    
IN    EAX,DX    ;读数据口
MOV    dword ptr IO_9054base_address,EAX    
AND    EAX,1    
JZ    findPCI_next    ;检查是否为 i/o 基址信息
MOV    EAX,dword ptr IO_9054base_address    
AND    EAX,0fffffffeh    
MOV    dword ptr IO_9054base_address,EAX    ;去除 i/o 指示位并保存
MOV    DX,IO_port_addre    
MOV    EAX,EBX    
ADD
OUT    EAX,BADR2
DX,EAX    ;写地址口
MOV    DX,IO_port_data    
IN    EAX,DX    ;读数据口
 
 
MOV AND    dword ptr IO_base_address,EAX EAX,1    
JZ    findPCI_next    ;检查是否为 i/o 基址信息
MOV    EAX,dword ptr IO_base_address    
AND    EAX,0fffffffeh    
MOV    dword ptr IO_base_address,EAX    ;去除 i/o 指示位并保存
MOV     DX,offset good    ;显示开始执行程序信息
MOV    AH,09H
INT    21H
POPfd POPad RET
findPCI    ENDP
MY_CODE    ENDS END START

汇编示例

.model small
.stack 100h
.data
    hour db 2,":$"
    minute db 2,":$"
    second db 2,"$"
    buffer db 10 DUP("$")
    count db 0
.code
main proc
    mov ax, @data
    mov ds, ax
    
    ; 初始化屏幕
    mov ah, 0
    mov al, 3
    int 10h
    
    ; 显示时分秒
    mov ah, 2
    mov dl, hour
    int 21h
    mov dl, minute
    int 21h
    mov dl, second
    int 21h
    
    ; 开始计时
    mov ah, 0
    int 16h
    
start:
    ; 更新秒
    mov ah, 2
    inc second
    cmp second, 60
    jne time_ok
    mov second, 0
    inc minute
    cmp minute, 60
    jne time_ok
    mov minute, 0
    inc hour
    cmp hour, 24
    jne time_ok
    mov hour, 0
    jmp time_ok
time_ok:
    mov dl, hour
    int 21h
    mov dl, minute
    int 21h
    mov dl, second
    int 21h
    
    ; 监听空格键或Q键
    mov ah, 0
    int 16h
    cmp ah, 20h
    je pause
    cmp ah, 10h
    je exit
    
    ; 继续计时
    jmp start
    
pause:
    ; 显示暂停时刻
    cmp count, 10
    jae start
    mov ah, 2
    mov dl, '0' ; 十位
    int 21h
    mov dl, hour
    and dl, 0fh
    add dl, '0'
    int 21h
    mov dl, ':'
    int 21h
    mov dl, '0' ; 分钟十位
    int 21h
    mov dl, minute
    and dl, 0fh
    add dl, '0'
    int 21h
    mov dl, ':'
    int 21h
    mov dl, '0' ; 秒十位
    int 21h
    mov dl, second
    and dl, 0fh
    add dl, '0'
    int 21h
    inc count
    
    ; 继续监听键盘
    jmp start
    
exit:
    ; 显示暂停时刻
    mov ah, 2
    mov dl, 13
    int 21h
    mov dl, 10
    int 21h
    mov dl, "Paused Times:"
    int 21h
    mov cx, count
    mov si, OFFSET buffer
    mov ah, 2
    mov dl, 13
    int 21h
    mov dl, 10
    int 21h
    loop1:
        cmp cx, 0
        je end_loop1
        mov ah, 2
        mov dl, "  "
        int 21h
        mov dl, si[0]
        int 21h
        mov dl, ':'
        int 21h
        mov dl, si[2]
        int 21h
        mov dl, ':'
        int 21h
        mov dl, si[4]
        int 21h
        add si, 6
        dec cx
        jmp loop1
    end_loop1:
    
    ; 结束程序
    mov ah, 4ch
    mov al, 0
    int 21h
main endp
end main

汇编语言我不太熟,我给你找些资料,看下是否满足你的需求:
汇编课程设计报告计时器:https://www.docin.com/p-2701912997.html
用汇编语言编写一个时钟程序,在微机屏幕上显示当前时间的时、分、秒:https://zhidao.baidu.com/question/101839913.html
汇编语言:时钟实验:https://blog.csdn.net/m0_49448277/article/details/116291515

以上是我给你找的资料,你注意下最后一个博文,也是基于DOS的,应该与你的需求比较接近。


section .data
    time db 0       ; 计时器初始值为0
    pauseTimes db 0 ; 暂停时间计数器初始值为0
    pauseTable db 10 dup(0) ; 存储暂停时间的表格,最多10次暂停

section .text
    global _start
_start:
    mov ax, 0x0003 ; 将视频模式设置为文本模式
    int 0x10

    mov ah, 0x02 ; 设置光标位置
    mov bh, 0x00 ; 页号为0
    mov dh, 0x00 ; 行号为0
    mov dl, 0x00 ; 列号为0
    int 0x10

    mov ah, 0x01 ; 读取键盘输入
    int 0x16
    cmp al, 0x51 ; 如果按下的是 'Q' 键,则退出程序
    je _exit

    cmp al, 0x20 ; 如果按下的是空格键,则记录暂停时间
    jne _start

    cmp byte [pauseTimes], 10 ; 判断是否达到最大暂停次数
    jae _start

    mov ah, 0x02 ; 获取当前时间
    int 0x1A
    mov byte [pauseTable + bx], ch ; 存储小时数
    mov byte [pauseTable + bx + 1], cl ; 存储分钟数
    mov byte [pauseTable + bx + 2], dh ; 存储秒数

    inc byte [pauseTimes] ; 暂停时间计数器加一

    jmp _start

_exit:
    mov ah, 0x4C ; 退出程序
    xor al, al ; 返回值为0
    int 0x21