中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 扩展INT 13中DAP的数据在内存中的情况???
作者:
标题: 扩展INT 13中DAP的数据在内存中的情况??? 上一主题 | 下一主题
ilbgh11
初级用户





积分 60
发帖 21
注册 2008-7-17
状态 离线
『楼 主』:  扩展INT 13中DAP的数据在内存中的情况??? [已使用 LLM 解释]

我现在知道调用扩展INT13读写硬盘需要下面的参数:
AH=42/43(42读43写)
DL=驱动器号
DS:DI=DAP

其中DAP的结构是:
BYTE PacketSize; 数据包尺寸(恒为16字节)
BYTE Reserved; 保留,必须置0
WORD BlockCount; 要传输的数据块个数(以扇区为单位)
DWORD BufferAddr; 传输缓冲地址(segment:offset)
QWORD BlockNum; 磁盘起始绝对块地址

现在我想知道,假如我用下面的参数调用扩展INT13:

AH=42
DL=80
DS:DI=DAP
DS=1000
DI=0000
DAP
{
PacketSize=16
Reserved=0
BlockCount=1
BufferAddr=2000:0100
BlockNum=7
}

那么,在1000:0000处的数据是什么样子呢?
(从1000:0到1000:10的数据依次是什么)
会是下面这个样子吗?
10 00 01 00 00 01 00 20 07 00 00 00 00 00 00 00

这类程序我不常用,现在需要在DEBUG下运行,所以需要知道这些信息

Last edited by ilbgh11 on 2008-9-12 at 10:39 AM ]
LLM 解释

1. 首先明确DAP结构各字段的存储方式

DAP的结构按顺序依次是:

  • PacketSize:占1个字节,值为16,所以内存中对应位置是10h
  • Reserved:占1个字节,值为0,对应位置是00h
  • BlockCount:占2个字节,是要传输的数据块个数,这里是1,也就是0001h,在内存中是低字节在前,所以依次是01h00h
  • BufferAddr:占4个字节,是传输缓冲地址的偏移和段。这里偏移是0100h,段是2000h,所以依次是00h(偏移的低字节)、01h(偏移的高字节)、00h(段的低字节)、20h(段的高字节)。
  • BlockNum:占8个字节,是磁盘起始绝对块地址,这里是7,也就是0000000000000007h,所以依次是07h00h00h00h00h00h00h00h

2. 具体分析1000:0到1000:10处的数据

1000:0开始依次:

  • 第一个字节是PacketSize10h
  • 第二个字节是Reserved00h
  • 第三个字节是BlockCount的低字节:01h
  • 第四个字节是BlockCount的高字节:00h
  • 第五个字节是BufferAddr的低字节(偏移部分):00h
  • 第六个字节是BufferAddr的高字节(偏移部分):01h
  • 第七个字节是BufferAddr的低字节(段部分):00h
  • 第八个字节是BufferAddr的高字节(段部分):20h
  • 第九个字节是BlockNum的低字节:07h
  • 第十个字节到第十六个字节是BlockNum的其余字节,都是00h

所以1000:01000:10处的数据应该是: 10 00 01 00 00 01 00 20 07 00 00 00 00 00 00 00

在DEBUG下查看的话,可以用D 1000:0 L16命令来查看从1000:0开始16个字节的内容,会得到上述结果。

3. 关于不同实现方式的补充

方式一:使用高级语言模拟(以C语言为例)

#include <stdio.h>
#include <dos.h>

struct DAP {
    unsigned char PacketSize;
    unsigned char Reserved;
    unsigned short BlockCount;
    unsigned long BufferAddr;
    unsigned __int64 BlockNum;
};

int main() {
    struct DAP dap;
    dap.PacketSize = 16;
    dap.Reserved = 0;
    dap.BlockCount = 1;
    dap.BufferAddr = 0x20000100; // 这里将段和偏移组合成一个长整型,低4字节是偏移,高4字节是段
    dap.BlockNum = 7;

    union REGS regs;
    regs.h.ah = 0x42;
    regs.h.dl = 0x80;
    regs.x.ds = 0x1000;
    regs.x.di = (unsigned int)&dap;

    int86(0x13, &regs, &regs);

    return 0;
}

在这个C语言代码中,通过定义DAP结构体来模拟DAP结构,然后使用int86函数来调用中断13h的扩展功能。这里需要注意数据在结构体中的存储顺序要符合DAP的结构要求。

方式二:纯汇编实现

.model small
.stack 100h

.data
    dap db 16, 0, 0, 1, 0, 1, 0, 20h, 7, 0, 0, 0, 0, 0, 0, 0 ; 按照DAP结构依次定义数据
    buffer db 100 dup(0) ; 模拟传输缓冲

.code
main proc
    mov ax, 0x1000
    mov ds, ax
    mov di, offset dap

    mov ah, 0x42
    mov dl, 0x80
    int 0x13

    mov ah, 0x4c
    int 0x21
main endp
end main

在这个汇编代码中,先定义了DAP结构的数据和传输缓冲,然后设置相关寄存器的值,调用中断13h的扩展读功能。这里要特别注意数据在内存中的存储顺序必须严格符合DAP的结构,以保证中断调用能够正确识别参数。



2008-9-12 10:35
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
cjt211
新手上路





积分 8
发帖 2
注册 2006-4-11
状态 离线
『第 2 楼』:   使用 LLM 解释/回答一下

没有错,表示从lba7的地方读1个扇区到2000:100


2008-9-12 14:14
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
netwinxp
高级用户





积分 741
发帖 366
注册 2007-7-25
状态 离线
『第 3 楼』:   使用 LLM 解释/回答一下

1、注意BlockCount不要超过127。
2、LBA地址是从0开始的。


2008-9-15 08:34
查看资料  发短消息  网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: