Xexux 2023-12-11 23:20 采纳率: 0%
浏览 5
已结题

写操作系统:qemu读取数据块有问题?

我在测试我自己写的操作系统boot时遇到了个很奇怪的问题:
我的boot中有一个功能,将内核文件SYS读取到内存中。
因为是用FAT16,所以一个簇一个簇地读取(我把簇大小设成了512字节)
在中间我设计了个测试代码,每成功读取一个簇,就输出对应的簇号:


;输出测试信号
add al,48
mov byte gs:[si],al
mov byte gs:[si+1],0xc
sub al,48
add si,2

(gs的值是0xb800,al存储的是簇号,si是视频内存偏移地址,起始为0)
我用了qemu和bochs两个测试了同样的代码,结果:

img

img

bochs可以成功读取,然而qemu却莫名其妙地在读完第一个簇之后代码跑飞,然而我的boot代码并没有能让代码跑飞的部分。

img

(跑飞的代码。我这里根本没写任何东西,也没有任何跳转指令指向这个地方!)

更奇怪的是,如果我在qemu使用si命令一步步执行,它就不会跑飞,能够正确读取我的簇?
这究竟是什么问题?
附上关键代码:


.found:

;获取首簇号
sub di,8
add di,0x1a;偏移到首簇号
mov word ax,[di]
mov bx,0
mov si,0
.read_f:
mov cx,1
push si
push ax
add ax,CLUSTER_SEC_BALANCE
call read_disk
pop ax
pop si
;输出测试信号
add al,48
mov byte gs:[si],al
mov byte gs:[si+1],0xc
sub al,48
add si,2

;获取下一个簇号
mov di,0x8000
shl ax,1
add di,ax
mov ax,[di]
cmp ax,0xfff8
jb .read_f
go_to_kernel:
    jmp 0:0

read_disk:
    push ebp
    mov ebp,esp
    mov dx,0x1f7
;.not_ready1:
    ;nop ;nop相当于稍息 hlt相当于睡觉
    ;in al,dx ;读0x1f7端口
    ;and al,0xc0 ;第7位为1表示硬盘忙,第6位为1表示硬盘控制器已准备好,正在等待指令。
    ;cmp al,0x40 ;当第7位为0,且第6位为1,则进入下一个步。
    ;jne .not_ready1 ;若未准备好,则继续判断。

    ;xor ecx,ecx
    ;mov eax,[esp+8];lba
    ;mov ecx,[esp+12];counts(actually only data in cl are valid)
    ;mov ebx,[esp+16];mem_addr
    mov esi,eax;start LBA
    mov dx,0x1f2;设置读取的扇区数
    mov al,cl
    out dx,al

    mov dx,0x1f3
    mov eax,esi
    out dx,al;0-7bit(LBA)

    inc dx
    shr eax,8
    out dx,al;8-15bit

    inc dx
    shr eax,8
    out dx,al;16-23bit

    inc dx
    shr ax,8
    and al,0x0f
    or al,0xe0
    out dx,al;24-27bit and set some disk args

    inc dx
    mov al,0x20
    out dx,al;read disk
.wait:
    nop
    in al,dx
    ;check errors
    push ebx
    mov bl,al
    and bl,0x01
    cmp bl,1
    je .err_disk_reading

    and al,0x88
    cmp al,0x08
    jne .wait
;0x88=0b10001000
;0x51=0b01010001
    ;pop ebx
    mov di,dx

    shl ecx,8;每次读取2byte,所以要读取512/2*cl次

    mov dx,0x1f0
.read:
    in ax,dx
    mov word [ebx],ax
    add ebx,2
    loop .read

    mov esp,ebp
    pop ebp
    mov eax,0
    ret
.err_disk_reading:
    mov dx,0x1f1
    xor eax,eax
    in ax,dx;ax=0xffff
    ;pop ebx
    
    mov si,diskerror
    mov di,0
    call print_g

    mov esp,ebp
    pop ebp
    ret
  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 12月19日
    • 创建了问题 12月11日

    悬赏问题

    • ¥15 Vue3 大型图片数据拖动排序
    • ¥15 划分vlan后不通了
    • ¥15 GDI处理通道视频时总是带有白色锯齿
    • ¥20 用雷电模拟器安装百达屋apk一直闪退
    • ¥15 算能科技20240506咨询(拒绝大模型回答)
    • ¥15 自适应 AR 模型 参数估计Matlab程序
    • ¥100 角动量包络面如何用MATLAB绘制
    • ¥15 merge函数占用内存过大
    • ¥15 使用EMD去噪处理RML2016数据集时候的原理
    • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大