• See You Again——我最后的汇编程序


    汇编语言:课程设计2

    前言

    由于本人水平不够,这里的课程设计2的程序实现并没有像王爽书中所说的那样可以不依赖于操作系统运行。
    这里的程序依然要在dos下运行,而且没有实现引导现有操作系统的功能。
    该程序的功能如下:
    1) reset pc ;重新启动计算机
    2) clock ;进入时钟程序
    3) set clock ;设置时间
    4) exit ;退出程序

    说明:
    (1)用户按下“1”后重新启动计算机
    (2)用户按下“2”后,执行动态显示当前日期、时间的程序。显示格式:年/月/日 时:分:秒
    进入此功能后,一直动态显示当前时间,在屏幕上将出现时间按秒变化的效果(循环读取CMOS)
    当按下F1至F7键后,显示不同的文字颜色。按下Esc键后,返回主菜单。
    (3)用户按下“3”后可更改当前的日期、时间,更改后返回主菜单。
    (4)用户按下“4”后,退出程序。

    遗憾

    实际编程的过程中,功能3——修改当前时间没有完成,虽然代码中也加入了写入71h端口的指令,但是没有卵用,读取CMOS依旧是原来的时间。
    这个程序原来功能2中修改显示颜色的功能原本是想只按F1键,依次切换7种颜色的,但是调试时发现问题(颜色的显示简直是随机的!!),后来才改成F1~F7键,按一个键,换一种颜色。
    最大的遗憾就是没有实现在裸机上跑。我对什么软盘映像文件,引导,虚拟机是很头疼的(好吧,我承认就是我比较菜,而且还懒得自学)

    实现

    其实代码比较垃圾,只是贴出来纪念一下。

    其中的重启计算机的指令可以这么写:

    mov     ax,0ffffh
    push    ax
    mov     ax,0
    push    ax
    retf

    这就是对retf指令的灵活运用!而我却没有想到,即使我能轻松读懂这段指令。我的做法是:在数据段保存跳转地址,用jmp指令实现。
    关于int 16h中断例程,我用了0号功能,从BIOS键盘缓冲区中取出ASCII码(或扫描码),这里我就不详细介绍了。简单来说,int 9中断例程是向键盘缓冲区写入数据(可以从60h端口读出扫描码),int 16h中断例程就是从键盘缓冲区读出数据。

    功能3中,我参考书中的字符串输入的程序,自己实现了一个只适用于功能3的日期时间输入子程序。这里要简单介绍一下字符串输入的实现思想。不同于高级语言,汇编的世界里字符串输入是要自己实现的。
    字符串的输入有下面的要求:

    • 输入的同时显示字符串(有回显)
    • 输入回车符后,字符串输入结束(回车键释放缓冲区)
    • 退格键删除已经输入的字符

    这里要用到“栈”这一简单的数据结构,编程思路如下:

    1. 调用int 16h读取键盘输入
    2. 如果是字符,进入字符栈,显示字符栈中所有字符,再转到步骤1
    3. 如果是退格键,从字符栈中弹出一个字符,显示字符栈中所有字符,再转到步骤1
    4. 如果是Enter键,结束输入过程

    代码清单如下:

    assume  cs:code,ds:data
    data    segment
            dw  0,0ffffh                ;4byte(offset:0~3)
            db  '1) reset pc     '
            db  '2) clock        '
            db  '3) set clock    '
            db  '4) exit         '      ;64byte(offset:4~67)
    time    db  '00/00/00 00:00:00'     ;17byte(offset:52~68)
    list    db  9,8,7,4,2,0             ;
    pos     dw  0,1,3,4,6,7,9,10,12,13,15,16
    des     dw  0,2,6,8,12,14,18,20,24,26,30,32
    top     dw  0       ;top变量的范围:0~24
    data    ends        ;top变量的作用:确定数字在屏幕上的位置des,
                        ;              确定缓冲区中数据的位置pos
    code    segment
    main:           call    clear
                    call    menu
        s:          mov     ah,0
                    int     16h
    
                    cmp     al,'1'
                    je      do1
                    cmp     al,'2'
                    je      do2
                    cmp     al,'3'
                    je      do3
                    cmp     al,'4'      
                    je      exit
                    jmp     s
    
        do1:        call    reset_pc
    
        do2:        call    clear
                    call    clock
                    jmp     main
        do3:        call    set_clock
                    jmp     main
    
    exit:           mov     ax,4c00h
                    int     21h
    ;------------------------------------------
    ;子程序:clear
    ;功能:清屏
    clear:          push    bx
                    push    es
    
                    mov     bx,0b800h
                    mov     es,bx
                    mov     bx,0
        cls:        mov     byte ptr es:[bx],' '
                    add     bx,2
                    cmp     bx,2000
                    jb      cls
    
                    pop     es
                    pop     bx
                    ret
    ;------------------------------------------
    ;子程序:set_color
    ;功能:设置显示颜色
    ;入口参数: (al) = 颜色值(0~7)
    set_color:      push    bx
                    push    es
    
                    mov     bx,0b800h
                    mov     es,bx
                    mov     bx,1
    set_color_s:    mov     es:[bx],al
                    add     bx,2
                    cmp     bx,2000
                    jb      set_color_s
    
                    pop     es
                    pop     bx
                    ret 
    ;------------------------------------------
    ;子程序:menu
    ;功能:在屏幕上显示菜单选项
    menu:           push    ax
                    push    cx
                    push    si
                    push    di
                    push    es
    
                    mov     ax,data
                    mov     ds,ax
                    mov     ax,0b800h
                    mov     es,ax
    
                    mov     si,4
                    mov     di,160*5+30*2
                    mov     cx,4
        menu_s  :   push    cx
                    mov     cx,16
        menu_s1:    mov     al,[si]
                    mov     es:[di],al
                    inc     si
                    add     di,2
                    loop    menu_s1
                    add     di,160-16*2
                    pop     cx
                    loop    menu_s
    
                    pop     es
                    pop     di
                    pop     si
                    pop     cx
                    pop     ax
                    ret
    ;------------------------------------------
    ;子程序:reset_pc
    ;功能: 重启计算机
    reset_pc:       mov     ax,data
                    mov     ds,ax   
                    jmp     dword ptr ds:[0]
    ;------------------------------------------
    ;子程序:clock
    ;功能: 动态显示当前时间
    clock:          push    ax
                    push    bx
                    push    cx
                    push    si
                    push    di
                    push    es
    
                    mov     bx,0b800h
                    mov     es,bx
    
                    mov     bx,0
                    mov     di,160*5+30*2
        clock_init: mov     al,time[bx]
                    mov     byte ptr es:[di],al
                    inc     bx
                    add     di,2
                    cmp     bx,17
                    jb      clock_init
    
        show_time:  mov     di,160*5+30*2
                    mov     bx,0
                    mov     cx,6
        show_s:     push    cx
                    mov     al,list[bx]
                    out     70h,al
                    in      al,71h
                    mov     ah,al
                    mov     cl,4
                    shr     al,cl
                    and     ah,00001111b
                    add     ax,3030h
    
                    mov     es:[di],al
                    mov     es:[di+2],ah
                    add     di,3*2
                    inc     bx
                    pop     cx
                    loop    show_s
    
                    in      al,60h
                    cmp     al,1              ;按下Esc键返回主菜单
                    je      clock_ret
                    cmp     al,3bh
                    jb      show_time         ;按下F1~F7键更改显示颜色
                    cmp     al,41h
                    ja      show_time
                    ;更改显示颜色
        change:     sub     al,3ah  
                    call    set_color
                    jmp     short show_time
    
        clock_ret:  mov     al,7
                    call    set_color       
    
                    pop     es
                    pop     di
                    pop     si
                    pop     cx
                    pop     bx
                    pop     ax
                    ret
    ;------------------------------------------
    ;子程序:set_clock
    ;功能: 修改当前时间
    set_clock:      jmp     short set_start
        set_time    db  '00/00/00 00:00:00'         
    set_start:      push    ax
                    push    bx
                    push    cx
                    push    si
                    push    di
                    push    es
    
                    call    clear
                    mov     bx,0b800h
                    mov     es,bx
                    mov     bx,0
                    mov     di,160*5+30*2
    set_init:       mov     al,set_time[bx]
                    mov     es:[di],al
                    add     di,2
                    inc     bx
                    cmp     bx,17
                    jb      set_init
    
                    call    gettime
    
                    mov     si,0
                    mov     bx,0
        cset:       mov     al,list[si]
                    out     70h,al
                    mov     di,des[bx]
                    mov     ah,es:[160*5+30*2+di]
                    sub     ah,'0'
                    mov     cl,4
                    shl     ah,cl
                    mov     al,es:[160*5+30*2+2+di]
                    sub     al,'0'
                    add     al,ah
                    out     71h,al
                    add     bx,2*2
                    inc     si
                    cmp     si,6
                    jb      cset
    
    
                    pop     es
                    pop     di
                    pop     si
                    pop     cx
                    pop     bx
                    pop     ax
                    ret
    ;-------------------------------------------
    ;子程序:gettime
    ;功能:输入时间
    gettime:        push    ax
    
        gets:       mov     ah,0
                    int     16h
                    cmp     al,'0'
                    jb      nodigit
                    cmp     al,'9'
                    ja      nodigit
                    mov     ah,0
                    call    charstack
                    mov     ah,2
                    call    charstack
                    jmp     gets
    
        nodigit:    cmp     ah,0eh
                    je      backspace
                    cmp     ah,1ch
                    je      _enter
                    jmp     gets
    
        backspace:  mov     ah,1
                    call    charstack
                    mov     ah,2
                    call    charstack
                    jmp     gets
    
        _enter:     mov     ah,2
                    call    charstack
    
                    pop     ax
                    ret
    ;-------------------------------------------
    ;子程序:charstack
    ;入口参数:
    ;(ah) = 功能号, 0表示入栈, 1表示出栈,2表示显示
    ;对于功能0: (al) = 入栈字符
    charstack:      jmp     short charstart
            table   dw  charpush,charpop,charshow   
    charstart:      push    ax
                    push    bx
                    push    si
                    push    di
                    push    es
    
                    cmp     ah,2
                    ja      chret
                    mov     bl,ah
                    mov     bh,0
                    add     bx,bx
                    jmp     word ptr table[bx]      
    
    charpush:       cmp     top,24      ;边界情况处理
                    je      chret       
                    mov     bx,top                  
                    mov     si,pos[bx]
                    mov     time[si],al
                    add     top,2
                    jmp     chret
    
    charpop:        cmp     top,0       ;边界情况处理
                    je      chret
                    sub     top,2
                    jmp     chret
    
    charshow:       mov     bx,0b800h
                    mov     es,bx
                    mov     di,0
                    mov     bx,0
    
        charshows:  mov     si,pos[bx]
                    cmp     bx,top
                    jne     noempty
                    cmp     bx,24       ;边界情况处理,确保数字屏显正常
                    je      chret
                    mov     byte ptr es:[160*5+30*2+di],'0'
                    jmp     chret
        noempty:    mov     al,time[si]
                    mov     es:[160*5+30*2+di],al
                    add     bx,2
                    mov     di,des[bx]
                    jmp     charshows
    
    chret:          pop     es
                    pop     di
                    pop     si
                    pop     bx
                    pop     ax
                    ret
    ;------------------------------------------
    code    ends
    end     main

    演示画面

    菜单页面
    菜单页面

    重启电脑
    重启电脑

    时间显示(绿色)
    时间显示

    结束语

    第一阶段汇编语言的自学到这里就告一段落了,虽然留下了不少遗憾,但也有不少收获。这次课程设计是我最后的汇编程序了,有一些功能没有实现,以后我也不准备弥补了。这就好像所有的期末(升学)考试一样,即使考得再差,也不会有老师在考完后评讲试卷,不会有学生修改错题。这次课程设计的源程序不久就会被删除(垃圾总是要清理的,笑),接下来我要复习C语言,应付来年的计算机二级考试。
    第二阶段的汇编语言学习,我已经有了初步的计划,参考书是《x86汇编语言——从实模式到保护模式》。什么时候开始新阶段的学习呢?看我心情吧。(也可能转变学习方向,学习AT&T格式的汇编)

  • 相关阅读:
    HDU 5441——Travel——————【并查集+二分查界限】
    HDU 5446——Unknown Treasure——————【CRT+lucas+exgcd+快速乘+递推求逆元】
    HDU 5407——CRB and Candies——————【逆元+是素数次方的数+公式】
    HDU 5412——CRB and Queries——————【线段树套Treap(并没有AC)】
    HDU 4336——Card Collector——————【概率dp】
    HDU 5419——Victor and Toys——————【线段树|差分前缀和】
    使用 Jersey 和 Apache Tomcat 构建 RESTful Web 服务
    使用 JAX-RS 简化 REST 应用开发
    [置顶] 智能家居开源项目 The open Home Automation Bus (openHAB)
    ThoughtWorks 技术雷达(2013年5月)
  • 原文地址:https://www.cnblogs.com/wyf12138/p/6581521.html
Copyright © 2020-2023  润新知