LINUX --- 中断 --- INT 0x13

本文详细介绍了INT13H中断中的几个关键磁盘操作功能,包括磁盘控制器复位、读写扇区、检测扇区等,并提供了具体的调用示例代码。此外还列举了可能遇到的错误状态及其含义。

中断INT13功能及用法分析


INT 13H,AH=00H 软、硬盘控制器复位
说明:
此功能复位磁盘(软盘和硬盘)控制器板和磁盘驱动器,它在磁盘控制器
芯片上完成复位操场作并在磁盘进行所需的操作之前做一系列用于磁盘校准的
磁盘操作。
当磁盘I/O功能调用出现错误时,需要调用此功能,此刻复位功能将使BIOS
象该磁盘重新插入一样检查驱动器中磁盘状态,并将磁头校准使之在应该在的
位置上。
此功能调用不影响软盘或硬盘上的数据。
入口参数:
AH=00H 指明调用复位磁盘功能。
DL 需要复位的驱动器号。
返回参数:
若产生错误,进位标志CF=1,错误码在AH寄存器。
详情请见磁盘错误状态返回码一文。
示例:
C_SEG SEGMENT PUBLIC
ASSUME CS:C_SEG,DS:C_SEG
ORG 100H
START: MOV AH, 00H
MOV DL, 80H
INT 13H
;复位硬盘 C
JC ERROR
……
ERROR: ……
C_SEG ENDS
END START

INT 13H,AH=02H 读扇区说明:
调用此功能将从磁盘上把一个或更多的扇区内容读进存贮器。因为这是一个
低级功能,在一个操作中读取的全部扇区必须在同一条磁道上(磁头号和磁道号
相同)。BIOS不能自动地从一条磁道末尾切换到另一条磁道开始,因此用户必须
把跨多条磁道的读操作分为若干条单磁道读操作。
入口参数:
AH=02H 指明调用读扇区功能。
AL 置要读的扇区数目
,不允许使用读磁道末端以外的数值,也不允许
使该寄存器为0。
DL 需要进行读操作的驱动器号。
DH 所读磁盘的磁头号。
CH 磁道号的低8位数。
CL 低5位放入所读起始扇区号,位7-6表示磁道号的高2位。
ES:BX 读出数据的缓冲区地址。
返回参数:
如果CF=1,AX中存放出错状态。读出后的数据在ES:BX区域依次排列。
详情请参见磁盘错误状态返回码一文。
示例:
C_SEG SEGMENT PUBLIC
ASSUME CS:C_SEG,DS:C_SEG
ORG 100H
START: JMP READ
BUFFER DB 512 DUP(0)
READ: PUSH CS
POP ES
MOV BX, OFFSET BUFFER
MOV AX, 0201H
MOV CX, 0001H
MOV DX, 0000H
INT 13H
;读软盘A, 0面0道1扇区
;读出后数据在BUFFER中
JC ERROR
……
ERROR: ……
C_SEG ENDS
END START

INT 13H,AH=03H 写扇区

说明:
调用此功能将从磁盘上把一个或更多的扇区内容写入驱动器。因为这
是一个低级功能,在一个写入操作中的全部扇区必须在同一条磁道上(磁
头号和磁道号相同)。BIOS不能自动地从一条磁道末尾切换到另一条磁道
开始,因此用户必须把跨多条磁道的写操作分为若干条单磁道写操作。
入口参数:
AH=03H 指明调用写扇区功能。
AL 置要写的扇区数目
,不允许使用超出磁道末端以外的数值,
也不允许使该寄存器为0。
DL 需要进行写操作的驱动器号。
DH 所写磁盘的磁头号。
CH 磁道号的低8位数。
CL 低5位放入所读起始扇区号,位7-6表示磁道号的高2位

ES:BX 放置写入数据的存贮区地址。
返回参数:
如果CF=1,AX中存放出错状态。
详情请参见磁盘错误状态返回码一文。
示例:
C_SEG SEGMENT PUBLIC
ASSUME CS:C_SEG,DS:C_SEG
ORG 100H
START: JMP WRITE
BUFFER DB 512 DUP(0FFH)
WRITE: PUSH CS
POP ES
MOV BX, OFFSET BUFFER
MOV AX, 0301H
MOV CX, 0001H
MOV DX, 0000H
INT 13H
;写入软盘A, 0面0道1扇区
;把此扇区数据全部置为0FFH
JC ERROR
……
ERROR: ……
C_SEG ENDS
END START

INT 13H,AH=04H 检测扇区

说明:
这个功能检测磁盘上1个或更多的扇区。这个验证测试不是把磁盘上的
数据和内存中的数据进行比较,而只是简单地确定读出的数据有无CRC错误。
这个功能可用来验证驱动器中的软盘版。如果盘片的格式正确,CF=0。
入口参数:
AH=03H 指明调用检测扇区功能。
AL 置要检测的连续扇区数目,不允许使用超出磁道末端以外的
数值,也不允许使该寄存器为0。
DL 需要进行检测的驱动器号。
DH 磁盘的磁头号。
CH 磁道号的低8位数。
CL 低5位放入起始扇区号,位7-6表示磁道号的高2位。
返回参数:
如果CF=1,AX中存放出错状态。CF=0,检测正确。
详情请参见磁盘错误状态返回码一文。
示例:
C_SEG SEGMENT PUBLIC
ASSUME CS:C_SEG,DS:C_SEG
ORG 100H
START: MOV AX, 0401H
MOV CX, 0001H
MOV DX, 0000H
INT 13H
;检测软盘A, 0面0道1扇区
JC ERROR
……
ERROR: ……
C_SEG ENDS
END START

磁盘错误状态返回码:

磁盘错误状态

AH=
00H 未出错
01H 非法功能调用命令区。
02H 地址标记损坏,扇区标识(ID)无效或未找到。
03H 企图对有写保护的软盘执行写操作。
04H 所寻找的扇区没找到。
05H 复位操作失败。
06H 无介质。
07H 初始化错误,数据未存在DMA的64K缓冲区内。
08H DMA故障
09H DMA边界错误,数据未存在DMA的64K缓冲区内。
0AH 检测出错误码率的扇区标志。
0BH 所寻找的磁道没找到。
0CH 介质类型没发现。
0DH 扇区号有问题。
0EH 发现控制数据地址标记。
0FH 超出DMA边界
10H 读磁盘时奇偶校验错,且纠错码(EDC)不能纠正。
11H 读磁盘时奇偶校验错,但纠错码(EDC)已纠正错误。
20H 控制器错。
40H 查找操作无效。
80H 超时错误,驱动器不响应。
AAH 驱动器未准备好。
BBH 不明错误。
CCH 被选驱动器出现写故障。
E0H 错误寄存器是零
FFH 非法操作。

全面的英文参考文档:http://en.wikipedia.org/wiki/INT_13H

<think>好的,我现在需要帮助用户了解如何在Linux中读取寄存器地址范围0x100000000x10000200的数据。首先,我得理解用户的具体需求。寄存器通常是指硬件设备中的寄存器,这可能属于某个外设或者特定的硬件模块。用户提到的地址范围属于物理地址,所以在Linux用户空间直接访问可能会有问题,因为用户空间程序通常无法直接访问物理内存。 接下来,我需要考虑不同的方法来实现这个目标。常见的方法可能有以下几种:使用/dev/mem设备文件,编写内核模块,或者通过已有的驱动程序接口。每种方法都有其优缺点,需要详细分析。 首先,使用/dev/mem。这个设备文件允许访问物理内存,但需要root权限,并且可能受到内核配置的限制,比如CONFIG_STRICT_DEVMEM选项是否启用。如果启用了这个选项,非设备内存区域的访问会被拒绝。所以用户需要先确认内核是否支持,可能需要重新编译内核。 然后,使用mmap将物理地址映射到用户空间。这里需要注意的是地址对齐的问题,通常mmap要求页对齐,所以0x100000000x10000200的跨度是0x200,即512字节,可能需要映射整个页(比如4KB)。用户需要计算正确的偏移量和映射长度,然后通过指针访问对应的位置。 另一种方法是编写内核模块,这样可以直接访问物理地址,权限更高。但编写内核模块需要一定的内核编程知识,并且存在风险,操作不当可能导致系统崩溃。用户可能需要使用ioremap来将物理地址映射到内核虚拟地址,然后进行读写操作。这种方法更灵活,但复杂度更高。 此外,用户可能已经有对应的设备驱动程序,通过设备节点的ioctl或者sysfs接口来访问寄存器。这种情况下,建议用户查阅相关设备的文档,使用现有的接口,这样更安全可靠。 还需要注意权限问题,无论是使用/dev/mem还是内核模块,都需要足够的权限。同时,直接操作硬件寄存器可能影响系统稳定性,特别是在多任务环境中,可能需要禁用中断或确保原子操作。 用户可能不太清楚这些方法的具体步骤,所以需要给出示例代码,比如使用dd命令读取/dev/mem,或者用C程序进行mmap映射。同时提醒用户谨慎操作,确保地址范围属于可安全访问的区域,避免访问关键系统区域导致系统崩溃。 最后,总结各种方法的适用场景,建议优先使用驱动程序接口,其次考虑/dev/mem,最后是内核模块。同时强调安全性和风险,确保用户了解潜在的问题。</think>在Linux系统中读取特定物理地址范围的寄存器数据(如0x10000000-0x10000200),需要根据具体场景选择合适的方法。以下是三种常见方案: 1. **通过/dev/mem设备访问(用户空间)** ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #define PHYS_ADDR 0x10000000 #define MAP_SIZE 0x200 // 512字节 int main() { int fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { perror("打开/dev/mem失败"); return EXIT_FAILURE; } void *map_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, fd, PHYS_ADDR); if (map_base == MAP_FAILED) { perror("内存映射失败"); close(fd); return EXIT_FAILURE; } // 读取示例:前4个字节 unsigned int value = *((unsigned int *)map_base); printf("0x%08x处的值: 0x%08x\n", PHYS_ADDR, value); munmap(map_base, MAP_SIZE); close(fd); return EXIT_SUCCESS; } ``` * 注意: - 需要root权限 - 内核需启用`CONFIG_STRICT_DEVMEM=n` - 地址必须页对齐(4KB边界) 2. **内核模块方案(更安全)** ```c #include <linux/init.h> #include <linux/module.h> #include <linux/io.h> #define PHYS_ADDR 0x10000000 #define REG_SIZE 0x200 static void __iomem *reg_base; static int __init reg_init(void) { reg_base = ioremap(PHYS_ADDR, REG_SIZE); if (!reg_base) { printk(KERN_ERR "地址映射失败\n"); return -ENOMEM; } // 读取示例 u32 value = ioread32(reg_base); printk(KERN_INFO "寄存器值: 0x%08x\n", value); return 0; } static void __exit reg_exit(void) { if (reg_base) iounmap(reg_base); } module_init(reg_init); module_exit(reg_exit); MODULE_LICENSE("GPL"); ``` 3. **使用现有驱动接口(推荐)** - 检查`/sys/class/`或`/proc/device-tree/` - 使用`ioctl`与设备驱动交互 - 示例(需具体设备支持): ```bash # 假设存在设备节点/dev/mydevice dd if=/dev/mydevice bs=4 count=128 skip=$((0x10000000/4)) 2>/dev/null | hexdump ``` **注意事项**: 1. 物理地址有效性需通过芯片手册确认 2. 访问前应确保: - 地址属于可访问区域 - 禁用内存管理单元(MMU)相关保护 - 必要时关闭中断 3. 生产环境建议通过正式驱动接口访问 4. X86架构需要处理IO端口保护 若遇到`mmap: Invalid argument`错误,可能是由于: - 地址未页对齐(需调整为0x10000000- 内核保护机制生效 - 物理地址不存在或受保护 建议先用`devmem2`工具测试: ```bash # 安装工具 sudo apt-get install devmem2 # 单次读取示例 sudo devmem2 0x10000000 w ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值