. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->使用BIOS进行键盘输入和磁盘读写
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  搞定了课程设计2!贴出代码!注释详细,欢迎交流~  [已解决] 回复[ 3次 ]   点击[ 456次 ]  
zjkl19
[帖 主]   [ 发表时间:2010-04-30 15:46 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:6
注册日期:2009-07-15 11:17
;终于把课程设计2干掉了!自己做的时候也想了非常久,就是那个org和那个什么AA55h的实在是想不通,书上没有。
        ;结果那些部分就参考了其它高手的代码,这里先感谢一下他们。

         ;bug:字符栈大小有限,输入过多字符会引起溢出(偷懒,不想加较检功能了^_^)
         ;不足之处:在屏幕显示字符串最好单独列个“showstring”之类的函数,不然真的挺麻烦的, 我一开
 ;始没注意这个问题,后来到程序快完工的时候才注意到,发现在屏幕加个string很麻烦,不过到最后懒得改了
        
         ;名称:综合模块
        ;功能:安装程序,实现所有功能

assume cs:code

code segment

        ;名称:安装模块
        ;功能:安装程序到软盘
        ;安装模块开始--------------------------------------------------------------------
        start:
                mov ax,cs
                mov es,ax
                mov bx,offset part1
                
                mov al,3                ;写3个扇区,实际引导程序包含2个部分,第一个512字节部分专门是用来导入后面两个512字节(共1024字节,也就是真正的主程序)的内容
                mov dh,0                ;0面
                mov ch,0                ;0磁道
                mov cl,1                ;1扇区
                mov dl,0                ;(dl)=0表示a盘        
                mov ah,3                ;(ah)=3表示写入,把cs:[offset part1]的内容写入到a盘头3个扇区
                int 13h
                
                mov ax,4c00h        ;返回到dos
                int 21h
        ;安装模块结束--------------------------------------------------------------------
        ;名称:part1
        ;说明:第一部分,512字节,负责把第二部分写入到0:7e00
        ;part1模块开始--------------------------------------------------------------------
        org 7c00h
        part1:
                mov ax,0
                mov es,ax
                mov bx,7e00h        
                
                mov al,2                ;读两个扇区,从软盘启动,int19h只读取一个扇区的内容,剩下的内容需要靠这个“中转程序”读出来。
                mov dh,0                ;0面
                mov ch,0                ;0磁道
                mov cl,2                ;2扇区
                mov dl,0                ;(dl)=0表示a盘        
                mov ah,2                ;(ah)=2表示读取
                int 13h
                mov ax,0h
                push ax
                mov        ax,7e00h
                push ax
                retf                        ;从cs:ip指向0:7e00h,因为0:7c00~0:7e00之间共512字节
        calc0:                                ;以上程序占31字节
                nop        
                db        512-(offset calc0-offset part1)-2 dup (0)                        ;把计算字节数这种麻烦事交给编译器
                dw 0AA55h                ;注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                                ;结果经过贴主测试,一下网上资料描述属实,我把0aa55h改成0,就无法引导了!
                                                ;以下引自网上资料: 
                        ;BIOS中断总是把主引导记录所在扇区(硬盘的0头0道1扇区)的内容(包括代码和数据)  
                        ;装入内存0000:7C00起始的区域,然后检验该扇区内容的最后两个字节是不是"AA55",  
                        ;如果不是,那么对不起,Int 19h将不把控制权交给主引导记录;若是,则主引导记录  
                        ;才能获得了控制权了(Int 19h通过跳转指令交转控制权) 

                                                
                                                
        ;part1模块结束--------------------------------------------------------------------
        ;名称:part2
        ;说明:功能主体部分
        ;part2模块开始--------------------------------------------------------------------
                jmp near ptr head
                stackchar        db        32 dup (0)
            table        dw charpush,charpop,charshow,l1,l2,l3,l4,timestr                ;timemod为第七位
                top         dw 0
            l1                db '1) reset pc',0
            l2                db '2) start system',0
            l3                db '3) clock',0
            l4                 db '4) set clock',0
                timestr        db 'yy:mm:dd hh:mm:ss',0
                cmos        db 9,8,7,4,2,0
                sign        db '// :: '
        
                pcreset        dd 0ffff0000h
                sysadd        dd 00007c00h
                
        head:
                call cls
                mov ax,0b800h
                mov es,ax
                mov si,10*160+32*2                ;10行32列,si定位列
                mov bp,0                                ;bp定位行
                mov bx,3                                ;bx定位l1、l2、l3、l4偏移
                
                call showmenu
        
        reinput:
                mov ah,0ch                                ;调用int21h的0ch子功能,清楚键盘缓冲区的内容,这个内容是书本上没有的,
                                                                ;本来我想用修改中断向量表的方法解决的,但是我嫌他麻烦,于是就用了这种办法
                int 21h        
                mov ah,0
                int 16h
                cmp al,'1'
                je ppcreset                
                cmp al,'2'
                je sysstart                
                cmp al,'4'
                je timemod
                cmp al,'3'
                jne reinput
                jmp near ptr clockhead
        ppcreset:        
                jmp dword ptr pcreset                        
        ;名称:sysstart
        ;功能:引导现有操作系统
        ;sysstart模块开始------------------------------------------------------
        sysstart:
                call cls
                mov ax,0
                mov es,ax
                mov bx,7c00h
                
                mov al,1                ;读1个扇区
                mov dh,0                ;0面
                mov ch,0                ;0磁道
                mov cl,1                ;1扇区
                mov dl,80h                ;C盘                
                mov ah,2                ;(ah)=2表示读取
                int 13h
                jmp dword ptr sysadd
        ;sysstart模块结束------------------------------------------------------
        ;名称:showmenu
        ;功能:显示主菜单
        ;说明:把这个模块单独列出来,而不是用显示字符串的方式分开列项目,原因是模块化编程思想
        ;showmenu模块开始------------------------------------------------------
        showmenu:        
                push bp                                        ;bp值最后恢复
                mov cx,4
                
        showstart:
                push bx
                push si
                push ax
                add bx,bx                                ;2个字节存放一个偏移地址
                mov bx,table[bx]                ;将偏移地址存放到bx
        shows:
                mov ah,cs:[bx]                        ;ah存放字符ascii码
                cmp ah,0
                je showret
                mov es:[bp+si],ah
                inc bx
                add si,2
                jmp short shows
                
        showret:
                pop ax
                pop si
                pop bx
                inc bx
                add bp,160
                
                loop showstart
                
                pop bp
                ret
        ;showmenu模块开结束------------------------------------------------------
        
                
        ;函数名称:cls模块
        ;功能:清屏
        ;参数返回:无
        cls:
                push cx
                push bx
                mov bx,0b800h
                mov es,bx
                mov cx,2000
                mov bx,0
        clsloop:
                mov byte ptr es:[bx],0
                add bx,2
                loop clsloop
                pop bx
                pop cx
                ret
        ;名称:timemod
        ;功能:修改cmos时间
        ;timemod模块开始------------------------------------------------------
        timemod:
                call cls
                mov bx,0b800h
                mov es,bx
                mov bx,7*2
                mov bx,table[bx]                ;将偏移地址存放到bx
                mov si,11*160+31*2
        reshow:
                mov ah,cs:[bx]                        ;ah存放字符ascii码
                cmp ah,0
                je timemodnext
                mov es:[si],ah
                inc bx
                add si,2
                jmp short reshow
        timemodnext:        
                mov ax,cs 
                mov ds,ax 
                mov dh,12
                mov dl,31
                mov si,offset stackchar                ;这一句非常重要
        call  getstr
        ;开始修改时间:
                mov cx,6
                mov si,0
                mov di,offset stackchar
        timeloop:
                push cx
                mov al,cmos[si]
                out 70h,al                ;通知COMS RAM要读写的端口
                
                mov ah,cs:[di]        ;(ah)=年份十位数        (第一次)
                sub ah,30h                ;得二进制码
                mov cx,4
                shl ah,cl
                mov        al,cs:[di+1]        ;(al)=年份个位数        (第一次)
                sub al,30h                ;得二进制码
                add al,ah                
                out 71h,al                ;把al写入到指定单元的数据
                inc si
                add di,3
                pop cx
                loop timeloop
                jmp near ptr head
        
        ;timemod模块结束------------------------------------------------------
        
        
        
        ;名称:clock模块
        ;功能:显示时间
        ;clock模块开始------------------------------------------------------
        clockhead:
                call cls                                                        ;显示时间前先清屏
        clock:
                
                mov ax,0b800h
                mov es,ax        
                mov cx,6
                mov si,0
                mov di,0
                mov bx,0
                
        
        sclock:
                mov al,cmos[si]
                out 70h,al
                in al,71h
                
                push cx
                mov ah,al
                mov ch,0
                mov cl,4
                shr ah,cl
                and al,00001111b
                
                add ah,30h
                add al,30h                ;ah存放十位数字,al存放个位数字                

                
                mov byte ptr es:[160*12+31*2+di],ah
                mov byte ptr es:[160*12+31*2+2+di],al
                mov ah,sign[bx]
                mov byte ptr es:[160*12+31*2+4+di],ah
                
                inc si
                inc bx
                add di,6
                pop cx
                loop sclock
                
                ;关键代码
                
                in al,60h
                
                cmp al,3bh        ;3bh是"F1"键的扫描码
        step1:
                jne        step2
                push cx
                push bx
                push ax
                mov bx,0
                mov al,es:[bx+1]
                inc al
                and al,00000111b
                mov cx,2000
                mov bx,1
        s1:
                and byte ptr es:[bx],11111000b
                or byte ptr es:[bx],al
                add bx,2
                loop s1
                pop ax
                pop bx
                pop cx
                jmp short step3
                
        step2:        
                cmp al,01h        ;01h是"ESC"键的扫描码
                                        ;返回主菜单前先清屏
                jne step3
                
                call cls
                jmp near ptr head
                
        step3:        
                
        
                jmp short clock
                
        ;clock模块结束------------------------------------------------------
                
        
        ;子程序:字符栈的入栈、出栈和显示
        ;参数说明:        (ah)=功能号,0表示入栈,1表示出栈,2表示显示
        ;                        ds:si指向字符栈空间
        ;                        对于0号功能:(al)=入栈字符
        ;                        对于1号功能:(al)=返回的字符
        ;                        对于2号功能:(dh)、(dl)=字符串在屏幕上显示的行、列位置
        
        ;charstack模块开始------------------------------------------------------
        charstack:        
                                                        ;有关charstack模块的内容,如果各位还有什么不大明白的话,
                                                        ;可以查阅17.3节的内容
        charstart:        
                push cx
                push dx
                push di
                push es
                
                cmp ah,2
                ja sret
                mov bl,ah
                mov bh,0
                add bx,bx
                jmp word ptr table[bx]
        charpush:
                mov bx,top
                mov [si][bx],al
                inc top
                jmp sret
        charpop:
                cmp top,0
                je sret
                dec top
                mov bx,top
                mov al,[si][bx]
                jmp sret
        charshow:
                mov bx,0b800h
                mov es,bx
                mov al,160
                mov ah,0
                mul dh
                mov di,ax
                add dl,dl
                mov dh,0
                add di,dx
                
                mov bx,0
        charshows:
                cmp bx,top
                jne noempty
                mov byte ptr es:[di],' '
                jmp sret
        noempty:
                mov al,[si][bx]
                mov es:[di],al
                mov byte ptr es:[di+2],' '
                inc bx
                add di,2
                jmp charshows
        sret:
                pop es
                pop di
                pop dx
                pop bx
                ret
        getstr:

                push ax
        getstrs:
                mov ah,0
                int 16h
                cmp al,20h
                jb nochar
                mov ah,0
                call charstack
                mov ah,2
                call charstack
                jmp getstrs
        nochar:
                cmp ah,0eh        ;"0eh"是退格键的扫描码
                je backspace
                cmp ah,1ch
                je enter0
                jmp getstrs
        backspace:
                mov ah,1
                call charstack
                mov ah,2
                call charstack
                jmp getstrs
        enter0:
                mov al,0
                mov ah,0
                call charstack
                mov ah,2
                call charstack
                pop ax
                ret
        ;charstack模块结束------------------------------------------------------

        ;part2模块结束--------------------------------------------------------------------                

code ends
end start
minghunjason
[第1楼]   [ 回复时间:2010-05-07 01:16 ]   [引用]   [回复]   [ top ] 
荣誉值:14
信誉值:2
注册日期:2009-08-13 10:23
恭喜你成功完成课设二,汇编论坛又要新增一个名单了。建议你再继续着手 综合研究。会有更大的收获,我看好多人完成课设二,就没继续了。其实综合研究 是精髓所在
zjkl19
[第2楼]   [ 回复时间:2010-05-07 23:40 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:6
注册日期:2009-07-15 11:17
回复:[第1楼]
------------------
谢谢~~
我完成了课程设计2的时候感觉也挺累了,把这本书放在一边去了,后来我把罗云彬那本《Windows环境下32位汇编语言程序设计》看了一章的时候,突然又想学C语言了,于是我时隔多日又重返汇编语言论坛的战场了!!!
这次我是从综合研究开始的!在看罗云彬那本书的时候我对windows的脾气也有了一些的了解,现在在回过头来看王爽的《汇编语言》又有新的感受了!
现在我已经把研究实验搞定两个了!
大家一起加油!!!!!!!!!!
zjkl19
[第3楼]   [ 回复时间:2013-12-12 11:02 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:6
注册日期:2009-07-15 11:17
此贴由 贴主 于 [ 2013-12-12 11:02 ] 结贴。 结贴原因:问题已解决
得分情况: 1楼(minghunjason):4分  
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved