汇编网首页登录博客注册
keyia的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新留言
好友圈
友情链接

[2009-04-01 10:36] 推荐博文 实验17 编写包含多个功能子程序的中断例程

实验17 编写包含多个功能子程序的中断例程

逻辑扇区的编号方法如下:
物理扇区号        逻辑扇区号
0面0道1扇区       0
0面0道2扇区       1
0面0道3扇区       2
0面0道4扇区       3
...
0面0道18扇区      17
0面1道1扇区       18
0面1道2扇区       19
0面1道3扇区       20
0面1道4扇区       21
...
0面1道18扇区      35
0面2道1扇区       36
0面2道2扇区       37
0面2道3扇区       38
0面2道4扇区       39
...
0面79道18扇区     1439
1面0道1扇区       1440
1面0道2扇区       1441
1面0道3扇区       1442
1面0道4扇区       1443
可以看出,逻辑扇区号和物理扇区号的关系如下:
逻辑扇区号=(面号*80+磁道号)*18+扇区号-1
面号=int(逻辑扇区号/1440)
磁道号=int(rem(逻辑扇区号/1440)/18)
扇区号=rem(rem(逻辑扇区号/1440)/18)+1
要求:安装一个新的int 7ch中断例程,实现通过逻辑扇区号对软盘进行读写。
参数说明:
(1)用ah寄存器传递功能号:0表示读,1表示写;
(2)用dx寄存器传递要读写的扇区的逻辑扇区号;
(3)用es:bx指向存储读出数据或写入数据的内存区。
(4)用al传送读取或写入的扇区数
分析:
根据前面的知识,可用int 13h的2号和3号功能对软盘的物理磁道进行读写。
思路:
搭建程序框架如下:
assume cs:code
code segment
;中断例程
          ;根据入口参数调用不同的功能子程序
;功能子程序A
;功能子程序B
start:
          ;安装
          ;写入偏移地址段地址
          ;初始化参数
          ;调用中断例程
          ;返回
code ends
end start

代码如下:

assume cs:code
stack segment
  db 128 dup (0)
stack ends
code segment
;=======================================
;int7ch功能子程序
;     名称:int7ch
;     功能:通过逻辑扇区号对软盘进行读写
;     入口:(ah)=功能号:0表示读,1表示写;
;          (al)=读出或写入的扇区数
;          (dx)=要读写的扇区的逻辑扇区号;
;          es:bx指向存储读出数据或写入数据的内存区。
;     返回:操作成功:(ah)=0,(al)=写入或读入的扇区数
;          操作失败:(ah)=出错代码
;=======================================
int7ch: jmp short int7chstart
    table dw int7ch0,int7ch1
    place db 0,0,0,0,0
int7chstart:push ax
            push bx
            push cx
            push dx
            push si
            push ds
            cmp ah,1
            ja int7chno                  ;长度限制不能直接ja int7chret
            jmp short int7chok
   int7chno:jmp int7chret
   int7chok:mov place[0],al              ;读出或写入的扇区数
            mov place[1],0               ;驱动器号
            mov al,0
            mov al,ah
            mov ah,0
            mov si,ax
            add si,si                    ;对应的功能子程序的偏移地址
            push si

            mov ax,dx
            mov dx,0
            mov cx,05A0h                 ;1440
            call divdw
            mov ah,0
            mov place[2],al              ;面号=int(逻辑扇区号/1440)
            mov ax,cx
            mov dx,0
            mov cx,012h                  ;18
            call divdw
            mov ah,0
            mov place[3],al              ;磁道号=int(rem(逻辑扇区号/1440)/18)
            add cl,1
            mov place[4],cl              ;扇区号=rem(rem(逻辑扇区号/1440)/18)+1  

            mov al,place[0]             ;读出的扇区数
            mov dl,place[1]             ;驱动器号
            mov dh,place[2]             ;磁头号(面)
            mov ch,place[3]             ;磁道数
            mov cl,place[4]             ;扇区号
            pop si
            jmp word ptr table[si]

    int7ch0:mov ah,2                    ;功能号
            int 13h
            jmp int7chret

    int7ch1:mov ah,3                    ;功能号
            int 13h
            jmp int7chret
;====================================== 
;名称:divdw 
      ;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。 
      ;参数:(ax)=dword型数据的低16位 
      ;     (dx)=dword型数据的高16位 
      ;     (cx)=除数 
      ;返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数 
;======================================  
divdw:
      push bx 
      push ax 
      mov ax,dx  ;被除数高位 
      mov dx,0 
      div cx     ;int(H/N)*65536,进行的16位除法,商返回给ax,余数返回给dx   
      mov bx,ax  ;bx存放商int(H/N) 
      push dx    ;dx为rem(H/N) 
      pop dx     ;dx传送[rem(H/N)*65536+L]/N的高位,  
      pop ax     ;存放[rem(H/N)*65536+L]/N的L 
      div cx     ;是16位除法,商返回给ax,余数返回给dx 
      mov cx,dx  ;返回结果余数 
      mov dx,bx  ;返回结果高位到dx,返回结果低位到ax,
                 ;int(H/N)*65536(dx存高位)+[rem(H/N)65536+L]/N(ax存低位,cx存余数) 
      pop bx 
ret
  int7chret:pop ds
            pop si
            pop dx
            pop cx
            pop bx
            pop ax
            iret
int7chend:nop

start:  ;安装中断程序到一个安全的地方0:200,实现通过逻辑扇区号对软盘进行读写
        mov ax,stack
        mov ss,ax
        mov sp,128
        mov ax,cs
        mov ds,ax
        mov ax,0
        mov es,ax
        mov si,offset int7ch
        mov di,200h
        mov cx,offset int7chend-offset int7ch
        cld
        rep movsb

        cli
        ;将中断程序的段地址偏移地址写入中断向量表
        mov ax,0
        mov es,ax
        mov word ptr es:[7ch*4],0h     ;!!!
        mov word ptr es:[7ch*4+2],20h

        ;初始化参数,测试代码从此处修改
        mov ax,cs
        mov ds,ax
        mov ax,0b800h
        mov es,ax
        sub ax,ax
        mov dx,1443                    ;要读写的扇区的逻辑扇区号
        mov bx,0                       ;es:bx指向存储读出数据或写入数据的内存区
        mov ah,0                       ;ah寄存器传递功能号:0表示读,1表示写
        mov al,8                       ;读出或写入的扇区数
        
        sti
        ;调用中断例程
        int 7ch

        ;返回
        mov ax,4c00h
        int 21h

code ends
end start

这道题的关键是搞清楚程序的入口
评论次数(5)  |  浏览次数(1501)  |  类型(汇编作业) |  收藏此文  | 

[  wsrf   发表于  2009-04-03 12:25  ]

程序结构很清晰,支持一下!

[  bslg123   发表于  2009-04-13 09:17  ]

牛!继续加油!

[  游客   发表于  2009-04-26 18:34  ]

你把13h写成13了

[  keyia   发表于  2009-04-29 10:02  ]

感谢指出问题

[  游客   发表于  2009-05-13 13:52  ]

谢了呀

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码