鱼C论坛

 找回密码
 立即注册
查看: 2655|回复: 1

[技术交流] 哎哟!费老大劲才完成《课程设计2》。

[复制链接]
发表于 2012-2-27 18:20:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 没个正样 于 2012-2-28 10:51 编辑

;哎哟!费老大劲才完成《课程设计2》。

;题目:课程设计2  
;阅读下面的材料:  
;开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。  
;初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。  
;硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。
;*****  
;如果设为从软盘启动操作系统,则int 19h将主要完成以下工作。  
;(1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;  
;(2)将CS:IP指向0:7c00。
;*****  
;软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。  
;如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作。  
;(1)读取硬盘C的0道0面1扇区的内容到0:7c00;  
;(2)将CS:IP指向0:7c00。  
;这次课程设计的任务是编写一个可以自行启动的计算机,不需要在现有操作系统环境中运行的程序。  
;该程序的功能如下:  
;(1)列出功能选项,让用户通过键盘进行选择,界面如下  
;1) reset pc          ;重新启动计算机  
;2) start system      ;引导现有的操作系统  
;3) clock             ;进入时钟程序  
;4) set clock         ;设置时间  
;(2)用户输入"1"后重新启动计算机(提示:考虑ffff:0单元)  
;(3)用户输入"2"后引导现有的操作系统(提示:考虑硬盘C的0道0面1扇区)。  
;(4)用户输入"3"后,执行动态显示当前日期、时间的程序。  
;显示格式如下:年/月/日 时:分:秒  
;进入此项功能后,一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果(提示: 循环读取CMOS)。  
;当按下F1键后,改变显示颜色;按下Esc键后,返回到主选单(提示:利用键盘中断)。  
;(5)用户输入"4"后可更改当前的日期、时间,更改后返回到主选单(提示:输入字符串)。
;功能:将代码写入0面0道1扇区

;入口参数:
;    (ah)=int 13h的功能号(2表示读扇区,3表示写扇区)
;    (al)=写入的扇区数
;    (ch)=磁道号
;    (cl)=扇区号
;    (dh)=磁头号(面号)
;    (dl)=驱动器号 (软区从0开始,0:软驱A,1:软驱B),{硬盘从80h开始,80h:硬盘C,81h:硬盘D}
;    es:bx指向将写入磁盘的数据或指向接收从扇区读入数据的内存区
;返回参数:操作成功:(ah)=0,(al)=写入的扇区数,          操作失败:(ah)=出错代码

;一,第一部分。(将引导信息数据写入某驱动器)
assume cs:code

code segment
start:mov ax,offset ydxxend-offset ydxx
   mov dx,0
   mov bx,512
   div bx             ;商ax为所需的扇区数
   cmp dx,0
   je ok               
   inc al             ;如果dx不等于0,那么证明有余数要加一个扇区。

ok:   mov bx,cs
      mov ds,bx
   mov bx,offset ydxx          ;es:bx指向要被开始读入的内存单元
   
   mov ah,3           ;int 13h的功能号(3表示写扇区)  
   mov ch,0           ;磁道号
   mov cl,1           ;扇区号(1处开始)
   mov d,0           ;磁头号(面号)
   mov dl,0           ;驱动器号,软盘A
   int 13h
   mov ax,4c00h
   int 21h
   
;二,第二部分。
ydxx: mov ax,offset ydxxend-offset ks1
   mov dx,0
   mov bx,512
   div bx             ;商ax为所需的扇区数
   cmp dx,0
   je ok1               
   inc al             ;如果dx不等于0,那么证明有余数要加一个扇区。

ok1:  mov bx,0
   mov es,bx
   mov bx,7c00h+200h          ;es:bx指向要被写入的内存单元
   
   mov ah,2           ;int 13h的功能号(2表示读扇区,3表示写扇区)  
   mov ch,0           ;磁道号
   mov cl,1           ;扇区号
   mov dh,0           ;磁头号(面号)
   mov dl,0           ;驱动器号,软盘A
   int 13h
      
   mov bx,7c0h
   push bx
   mov bx,offset ks1
   push bx
   retf  
   
ks1:  jmp d1
table dw  cd1,cd2,cd3,cd4            ;直接定址表   
cd   db '1) reset pc    ',0
      db '2) start system',0
      db '3) clock       ',0
      db '4) set clock   ',0
      db 'F1    /    Esc ',0
time  db 'ni/yu/re si:fe:ma',0
cmos  db 9,8,7,4,2,0
zb    db '     F1/Esc      ',0

;显示主菜单,调用show_str、qp子程序
d1:  call qp    ;清屏
     
     push cs
     pop ds
     mov si,offset cd
     mov dh,8
     mov dl,30
  
     mov cx,5
d0: push cx
     mov cl,7
     call show_str
  
     add si,16
     add di,160
     pop cx
     loop d0
  
;接收键盘输入,跳转相应功能程序段
;调用BIOS用来提供读取键盘缓冲区功能的中断例程int 16h,
;将读取的扫描码送入ah,ASCII码送入al
d2:  mov ax,0
     int 16h
  
     cmp al,'1'
     jb d1
     cmp al,'4'
     ja d1
     sub al,31h
     mov bl,al
     mov bh,0
     add bx,bx       ;计算相应子程序在table中的位移
  call word ptr table[bx]       ;调用对应的功能子程序
     jmp d1
  
;功能1:重新启动计算机
cd1:
     mov ax,0ffffh
     push ax
     mov ax,0
     push ax
     retf           ;jmp ffff:0
  
;功能2:引导现有的操作系统
;功能2实现引导现有的操作系统,代码需要将硬盘的0面0道1扇区读入0:7c00,
;会覆盖从软盘读到0:7c00的第一个扇区,所以功能2代码不能写在第一个扇区
cd2:call qp
     mov ax,0
     mov es,ax
     mov bx,7c00h
  
     mov ah,2       ;int 13h的功能号(2表示读扇区)  
     mov al,1       ;读取的扇区数
     mov ch,0       ;磁道号
     mov cl,1       ;扇区号
     mov dl,80h     ;驱动器号
     mov dh,0       ;磁头号(面号)
     int 13h        ;读取0面0道1扇区的内容到0:7c00h处
     mov ax,0
     push ax        ;push cs
     mov ax,7c00h
     push ax        ;push ip
     retf           ;jmp 0:7c00h

;功能3:进入时钟程序
cd3:     
     push ax
     push bx
     push cx
     push dx
     push si
     push ds
     push es
     call qp              ;清屏
     
     mov dh,24            ;行号
     mov dl,33            ;列号
     mov cl,7
     mov si,offset zb
     mov di,0
     call show_str        ;显示提示信息

;名称:dtsj
;功能:动态显示当前日期、时间
     mov cx,7          ;显示颜色
dtsj: push cx
     mov si,offset time
     mov bx,offset cmos
  
  mov cx,6
s0:     push cx
     mov al,[bx]
  out 70h,al       ;将al送入地址端口70h
  in al,71h       ;从数据端口71h处读出单元内容
  mov ah,al
  mov cl,4
  shr al,cl        ;右移4位
  and ah,00001111b ;al分成两个表示BCD码值的数据
  add ah,30h
  add al,30h       ;BCD码+30h=10进制数对应的ASCII码
  mov [si],ax      ;ASCII码写入ds:[si]
  
  inc bx
  add si,3
  pop cx
  loop s0
;按下F1键后,改变显示颜色
;按下Esc键后,返回主菜单,其他键照常处
     mov al,0
     in al,60h
  pop cx              ;显示颜色  
  
     cmp al,3bh          ;和F1的扫描码3bh比较
     je hdbz
  cmp al,1            ;和Esc的扫描码01h比较
     je dtsjend
  
     jmp zjxs
bs:  mov cx,0
     jmp zjxs  
hdbz:cmp cx,127
     je bs
     inc cx
zjxs:mov dh,12                 ;行号
     mov dl,33                 ;列号
     mov si,offset time
  mov di,0
     call show_str
  
     jmp dtsj                 ;循环显示CMOS  
dtsjend:
     pop es
     pop ds
     pop si
     pop dx
     pop cx
     pop bx
     pop ax
     ret


;功能4:设置时间
cd4: call qp
dtsj1:  mov si,offset time
     mov bx,offset cmos
  
  mov cx,6
s1:     push cx
     mov al,[bx]
  out 70h,al       ;将al送入地址端口70h
  in al,71h       ;从数据端口71h处读出单元内容
  mov ah,al
  mov cl,4
  shr al,cl        ;右移4位
  and ah,00001111b ;al分成两个表示BCD码值的数据
  add ah,30h
  add al,30h       ;BCD码+30h=10进制数对应的ASCII码
  mov [si],ax      ;ASCII码写入ds:[si]
  
  inc bx
  add si,3
  pop cx
  loop s1
        mov dh,12                 ;行号
        mov dl,33                 ;列号
        mov cl,7
  mov si,offset time
     mov di,0
        call show_str  
     
     mov si,offset time
     call getstr
     jmp near ptr ydxx
;完整的接收字符串输入的子程序
getstr: push ax
getstrs:
mov ah,0
int 16h

cmp al,20h
jb nochar     ;判断的是ASCII码小于0,说明不是字符
mov ah,0
call charstack  ;字符入栈
mov ah,2
call charstack  ;显示栈中的字符
jmp getstrs
nochar:
cmp ah,0eh   ;退格键的扫描码
je backspace
cmp ah,1ch   ;回车键的扫描码
je denter
jmp getstrs
  
backspace:    ;退格
mov ah,1
call charstack  ;字符出栈
mov ah,2
call charstack  ;显示栈中的字符
jmp getstrs
denter:     ;回车
mov al,0
mov ah,0
call charstack   ;0入栈
mov ah,2
call charstack  ;显示栈中的字符
pop ax
ret

;功能子程序实现
charstack:
jmp short charstart

tableb dw charpush,charpop,charshow
top    dw 0      ;栈顶

charstart:
push bx
push dx
push di
push es
cmp ah,2
ja sret
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr tableb[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


;名称:qp子程序
;功能:清屏
qp:  
     push bx
     push cx
     push es
  
     mov bx,0b800h
     mov es,bx
     mov bx,0
     mov cx,2000
qp0: mov byte ptr es:[bx],' '
     add bx,2
     loop qp0
  
     pop bx
     pop cx
     pop es
     ret
  
   
;名称:show_str子程序
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
;      (dl)=列号(取值范围0~79);
;      (cl)=颜色;
;      ds:si指向字符串的首地址。
;返回:无。
show_str:   ;显示字符串的子程序(定义开始)。
         push ax
         push bx
      push cx
         push dx
      push es
               push si
               push di
      
      mov al,0a0h   ;每行有160个字节,转换成16进制为A0。
         mul dh ;相当于从第(n-1)*0A0H个Byte单元开始......
      mov bx,ax    ;定位好的位置偏移地址存放在bx里(行)
      mov al,2    ;每个字符占两个字节
      mul dl     ;定位列,结果ax存放的是定位好的列的位置
      add bx,ax    ;此时bx中存放的是行与列号的偏移地址
      mov ax,0B800h  ;显存开始的地址
      mov es,ax   ;es中存放的是显存的第0页(共0--7页)的起始的段地址
      
      mov al,cl  ;cl是存放颜色的参数,这时候al存放颜色了,因为cl下边要用来临时存放要处理的字符
      
      mov ch,0         ;下边cx存放的是每次准备处理的字符
   s: mov cl,ds:[si]      ;ds:[si]指向“ ”,0
      jcxz ok3             ;当cl的值为0时候,cx == 0, 则发生跳转,到OK处结束处理!
      mov es:[bx+di],cl      ;偶地址存放字符
      mov es:[bx+di+1],al     ;奇地址存放字符的颜色属性
      inc si
      add di,2         ;指向了下个字符
      jmp short s      ;无条件跳转,jcxz是离开的关键跳!
   
   ok3:pop di
            pop si
      pop es
         pop dx
      pop cx
               pop bx
         pop ax
      ret        ;显示字符串的子程序[定义结束]   

ydxxend:nop

code ends
end start  

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2023-12-7 17:28:46 | 显示全部楼层
感谢大神分享!这个居然没人评论!说明看到这儿的人很少了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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