首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

LEA对硬盘端口写操作,该如何解决

2014-01-05 
LEA对硬盘端口写操作MBR.ASMSECTION ALIGN16 VSTART0x7C00LBA_BASE_ADDRESS EQU 5MOV AX , [cs:SS_B

LEA对硬盘端口写操作



;MBR.ASM
;
;
;
SECTION ALIGN=16 VSTART=0x7C00
LBA_BASE_ADDRESS EQU 5

MOV AX , [cs:SS_BASE]
MOV SS , AX
XOR SP , SP


MOV AX , [cs:DS_BASE]
MOV DS , AX
XOR BX , BX

MOV CX , 512

write_memory:
mov byte [bx] , 1
inc bx
loop write_memory
xor bx , bx

CALL WRITE_DISK
JMP $a

;
;
;
;DS:BX MEMORY ADDRESS
;
WRITE_DISK:
;Write disk
;Write a sector
mov dx , 0x1f2
mov ax , [cs:TARGET_PROGRAM_SIZE]
out dx , al

;Set write disk start sector address
mov dx , 0x1f3
mov al  , [cs:TARGET_PROGRAM_ADDRESS]
out dx , al
inc dx

mov al,0x00
out dx , al
inc dx
out dx , al
inc dx

mov al , 0xe0
OUT DX , AL

;设置写命令
MOV DX , 0x1F7
MOV AL , 0x30
OUT DX , AL
;
;
;判断是否硬盘还在忙 
MOV DX , 0x1F7
.DISKWAITS:
IN AL , DX
AND AL , 0x88
CMP AL , 0x08
JNZ .DISKWAITS
;写取一个扇区,512个字节,256个字 
MOV CX , 512
MOV DX , 0x1F0
.WRITESECTOR:
MOV AL , [BX] 
OUT DX , AL
INC BX 
LOOP .WRITESECTOR
RET
a

DS_BASE DW 0x1000
SS_BASE DW 0x2000
TARGET_PROGRAM_ADDRESS DB 0x03
TARGET_PROGRAM_SIZE DB 0x01

times 510 - ($-$$) db 0
dw 0xaa55


这是一个MBR程序我就是想往硬盘上写点数据,但是为什么执行了写不上数据?用nasm编译。bochs调试。
[解决办法]
直接端口操作来实现硬盘数据写入,有些麻烦啊,我也没做过,不知究里,为什么不简单些地使用 int13h 功能调用呢?
[解决办法]
记得给分哦!!!!

1.现代的硬盘都是PCI中断,你得遍历PCI总线查找ATAPI设备(包括光驱和硬盘),设备号好像是0201XXXXH
2.找到后配置寄存器空间偏移10H(应该是)是他的基地址(操作和170-1F0,1F0-1F7一样),170H-177H,1F0H-1F7H是并行硬盘的固定端口号,现在都是SATA硬盘,已经不用了。另外,你还得判断主从设备,一般硬盘是主设备,光驱是从设备,但也有例外。
3.用长命令发送。具体是每个端口发两遍,如扇区地址是12345678H,你的1F3-1F6只能发送28位,但是发两遍会寻址48位硬盘扇区
4.写硬盘DMA要用到配置空间20H的寄存器,具体看INTEL SPEC
5.写硬盘中断要到LPC资料看,5个步骤,很简单,要的话加分
6.还要配合硬盘分区,才能实现自己的文件驱动系统,想写的话我知道

[解决办法]
用BIOS 13H中断。 先是得到硬盘的分区表,然后可以就能对某个硬盘的扇区操作了。
[解决办法]
好久没来没看到啊,不好意思。
1. 会遍历 PCI总线么?PCI配置空间偏移08H-0BH是IDE硬盘的类型寄存器,高16位若是读出为0201H则为IDE硬盘,然后偏移10H-24H偏移的是控制寄存器和BUS MASTER(DMA),其中分别为PRIMARY MASTER,PRIMARY SLAVE,SECONDARY MASTER,SECONDARY SLAVE,BUS MASTER,就是主从控制器的命令寄存器,相当于170H,1F7H,我说的很明白了吧?
2.判断主从呢?还有偏移08H的字节,一般读出来是8FH或8AH,这个说起来很麻烦,要结合ATAPI协议来看,你主要看0ECH和0A1命令以及读写命令就行,一般48位扇区读写命令好像是29H和39H,比较简单的方法是一个一个的式。你把170H,1F7H,以及我上面说的4个命令寄存器挨个发读命令,若是返回值是58H,则肯定是IDE硬盘命令寄存器
我说的很清楚了吧,挨个试试,就这么简单,记得别忘了PCI的命令寄存器低2位清零哦
[解决办法]
这个是硬盘控制器的协议,所有硬盘都兼容这种接口,你放心吧,所有文件系统都基于这些内核代码,要是有时间,仔细看ATAPI协议
[解决办法]
最重要的是,还要看INTEL ICH芯片资料,都可以网上下载
[解决办法]
你的程序应该没问题,因为我是用MASM,TASM没用过,所以不能完全肯定,应该是端口错误
你这样得到端口地址,应该是2个,把他放到固定内存5000:0地址,用DEBUG 查看一下,再把上面的1F0等替换成现在的端口试试(必须在纯DOS下执行)

.386
code segment para 
assume cs:code
start:
mov ax,5000h
mov ds,ax
mov bx,0

mov eax,80000008h;从总线0,设备0,功能0,开始扫描硬盘控制器
SeekPciDevice:
push eax
;开始读PCI配置空间
mov edx,0cf8h
out edx,eax
mov edx,0cfch
in eax,edx
shr eax,16
cmp eax,0201h
jnz SeekNextDevice

FindAtapi:
;设备分类代码若为0201H则为硬盘控制器
add eax,8
;PCI配置空间偏移10H处为控制命令基地址
mov edx,0cf8h
out edx,eax
mov edx,0cfch
in eax,edx
and eax,0fffffffch
mov ds:[bx],ax
add bx,2


SeekNextDevice:
pop eax
add eax,100h
cmp eax,81000008h
jb SeekPciDevice
;总线大于255就是没有找到硬盘控制器
NoAtapi:
ret

[解决办法]
好像有个地方错了,汇编真麻烦
你的程序应该没问题,因为我是用MASM,TASM没用过,所以不能完全肯定,应该是端口错误
你这样得到端口地址,应该是2个,把他放到固定内存5000:0地址,用DEBUG 查看一下,再把上面的1F0等替换成现在的端口试试(必须在纯DOS下执行)

.386
code segment para 
assume cs:code
start:
mov ax,5000h


mov ds,ax
mov bx,0

mov eax,80000008h;从总线0,设备0,功能0,开始扫描硬盘控制器
SeekPciDevice:
push eax
;开始读PCI配置空间
mov edx,0cf8h
out edx,eax
mov edx,0cfch
in eax,edx
shr eax,16
cmp eax,0201h
jnz SeekNextDevice

FindAtapi:
pop eax ;上面少了这两句不对
push eax
add eax,8
;设备分类代码若为0201H则为硬盘控制器
;PCI配置空间偏移10H处为控制命令基地址
mov edx,0cf8h
out edx,eax
mov edx,0cfch
in eax,edx
and eax,0fffffffch
mov ds:[bx],ax
add bx,2


SeekNextDevice:
pop eax
add eax,100h
cmp eax,81000008h
jb SeekPciDevice
;总线大于255就是没有找到硬盘控制器
NoAtapi:
ret

热点排行