FunnyBishop 2021-05-27 13:41 采纳率: 0%
浏览 82

NASM汇编times 510-($-$$) db 0 为负报错??

RT,下附一图与代码

NUMsector      EQU    18       ; 最大扇区编号
NUMheader      EQU    1        ; 最大磁头编号
NUMcylind      EQU    5        ; 设置读取到的柱面编号

mbrseg         equ    7c0h     ; 启动扇区存放段地址
loaderseg      equ    800h     ; 从软盘读取LOADER到内存的段地址
kernalseg      equ    0c20h    ; 内核段地址 

jmp    short start             ; 为了制作PBP,第3个字节必须是 0x90。这里采用jmp short来占2字节 

        DB        0x90
        DB        "ImaGIPL"        ; 启动区的名称可以是任意字符串(8字节)
        DW        512                ; 每个扇区(sector)的大小必须为512字节
        DB        1                ; 簇(cluster)的大小必须为1个扇区
        DW        1                ; FAT的起始位置(一般从第一个扇区开始)
        DB        2                ; FAT的个数(必须为2)
        DW        224                ; 根目录的大小(一般设为244项)
        DW        2880            ; 该磁盘的的大小(必须为2880扇区)
        DB        0xf0            ; 磁盘的种类(必须为0xfd)
        DW        9                ; FAT的长度(必须为9扇区)
        DW        18                ; 一个磁道(track)有几个扇区(必须为18)
        DW        2                ; 磁头数(必须为2)
        DD        0                ; 不使用分区(必须为0)
        DD        2880            ; 重写一次磁盘大小
        DB        0,0,0x29        ; 意义不明,固定
        DD        0xffffffff        ; (可能是)卷标号码
        DB        "Imagine OS   "    ; 磁盘名称(11字节)
        DB        "FAT12   "        ; 磁盘格式名称(8字节)
        RESB    18                ; 先腾出18字节



start:

call showwelcome    ;初始化寄存器,打印必要信息 
call loader         ;执行loader,把现在这张软盘的数据全部读到8000h开始。 
jmp  kernalseg:0    ;跳转到内核。物理地址为c200h=8000h+4200h;8000为loader的
;开始地址,4200为kernal在FAT文件中的偏移地址
;注意jmp指令的操作后果,该跳转之后,CS=kernalseg=0c20h,IP=0,DS,ES保持不变。 

showwelcome: 
     mov   ax,mbrseg 
     mov   ds,ax   ;为显示各种提示信息做准备 
     mov   ax,loaderseg 
     mov   es,ax   ;为读软盘数据到内存做准备,因为读软盘需地址控制---ES:BX
     
     mov   si,welcome
     call  printstr
     call  newline
     ret

loader:
     mov   si, fyread
     call  printstr
     call  newline
     call  folppyload    ;将软盘的数据全部load到内存,从物理地址8000h开始 
     mov   si, Fycontent
     call  printstr
     call  showdata      ;可以验证一下从软盘读入的kernal程序数据是否正确(二进制) 
     ret



folppyload:                       
     call    read1sector
     MOV     AX,ES
     ADD     AX,0x0020
     MOV     ES,AX                ;一个扇区占512B=200H,刚好能被整除成完整的段,因此只需改变ES值,无需改变BP即可。 
     inc   byte [sector+11]
     cmp   byte [sector+11],NUMsector+1
     jne   folppyload             ;读完一个扇区
     mov   byte [sector+11],1
     inc   byte [header+11]
     cmp   byte [header+11],NUMheader+1
     jne   folppyload             ;读完一个磁头
     mov   byte [header+11],0
     inc   byte [cylind+11]
     cmp   byte [cylind+11],NUMcylind+1
     jne   folppyload             ;读完一个柱面

     ret
     
     
numtoascii:     ;将2位数的10进制数分解成ASII码才能正常显示。如柱面56 分解成出口ascii: al:35,ah:36
     mov ax,0
     mov al,cl  ;输入cl
     mov bl,10
     div bl
     add ax,3030h
     ret

readinfo:       ;显示当前读到哪个扇区、哪个磁头、哪个柱面 
     mov si,cylind
     call  printstr
     mov si,header
     call  printstr
     mov si,sector
     call  printstr
     ret


 
read1sector:                      ;读取一个扇区的通用程序。扇区参数由 sector header  cylind控制

       mov   cl, [sector+11]      ;为了能实时显示读到的物理位置
       call  numtoascii
       mov   [sector+7],al
       mov   [sector+8],ah

       mov   cl,[header+11]
       call  numtoascii
       mov   [header+7],al
       mov   [header+8],ah

       mov   cl,[cylind+11]
       call  numtoascii
       mov   [cylind+7],al
       mov   [cylind+8],ah

       MOV        CH,[cylind+11]    ; 柱面从0开始读
       MOV        DH,[header+11]    ; 磁头从0开始读
       mov        cl,[sector+11]    ; 扇区从1开始读        

        call       readinfo        ;显示软盘读到的物理位置
        mov        di,0
retry:
        MOV        AH,02H            ; AH=0x02 : AH设置为0x02表示读取磁盘
        MOV        AL,1            ; 要读取的扇区数
        mov        BX,    0         ; ES:BX表示读到内存的地址 0x0800*16 + 0 = 0x8000
        MOV        DL,00H           ; 驱动器号,0表示第一个软盘,是的,软盘。。硬盘C:80H C 硬盘D:81H
        INT        13H               ; 调用BIOS 13号中断,磁盘相关功能
        JNC        READOK           ; 未出错则跳转到READOK,出错的话则会使EFLAGS寄存器的CF位置1
           inc     di
           MOV     AH,0x00
           MOV     DL,0x00         ; A驱动器
           INT     0x13            ; 重置驱动器
           cmp     di, 5           ; 软盘很脆弱,同一扇区如果重读5次都失败就放弃 
           jne     retry

           mov     si, Fyerror
           call    printstr
           call    newline
           jmp     exitread
READOK:    mov     si, FloppyOK
           call    printstr
           call    newline
exitread:
           ret


printstr:                  ;显示指定的字符串, 以'$'为结束标记 
      mov al,[si]
      cmp al,'$'
      je disover
      mov ah,0eh
      int 10h
      inc si
      jmp printstr
disover:
      ret

newline:                     ;显示回车换行
      mov ah,0eh
      mov al,0dh
      int 10h
      mov al,0ah
      int 10h
      ret

showdata:  mov  si,0             ;验证显示从软盘读取到内存的数据 
           mov  ax, kernalseg 
           mov  es,ax
           mov  cx,9             ;控制输出的数据长度 
nextchar:  mov al,[es:si]
           mov ah,0eh
           int 10h
           inc si
           loop nextchar
           RET

welcome db 'Welcome Imagine OS!','$'
fyread  db 'Now Floppy Read Loader:','$'
cylind  db 'cylind:?? $',0    ; 设置开始读取的柱面编号
header  db 'header:?? $',0    ; 设置开始读取的磁头编号
sector  db 'sector:?? $',1    ; 设置开始读取的扇区编号
FloppyOK db '---Floppy Read OK','$'
Fyerror db '---Floppy Read Error' ,'$'
Fycontent db 'Floppy Content is:' ,'$'


times 510-($-$$) db 0
                 db 0x55,0xaa
  • 写回答

1条回答 默认 最新

  • weixin_45554038 2023-10-02 15:23
    关注

    510修改为1022即可

    评论

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型