Linux教程

汇编语言 — 课程设计2 — (二)重启计算机及引导现有操作系统

本文主要是介绍汇编语言 — 课程设计2 — (二)重启计算机及引导现有操作系统,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

        上一次完成了安装程序以及页面展示的代码编写,这次开始进行功能开发,本次开发前两个功能,分别是重新启动计算机以及引导现有的操作系统。

        这次是在上次的代码基础上进行功能开发,不过,代码上有所调整,添加了引导程序,为什么会这么做?下面会进行说明。

        首先给出调整后的代码,功能和(一)篇的内容一样,都是安装程序以及页面欢迎信息展示,不同的是添加了引导程序,以及将任务程序写入了 2 扇区。

boot segment                ; 将软盘中0道0面2扇区的任务程序读入到0:7e00处,然后跳转到该地址执行程序
    mov ax, 0               ; 7e00 = 7c00 + 200h,该偏移地址与7c00地址相差512字节,空出512字节空间,
    mov es, ax              ; 其它功能开发将会用到这空出的512字节空间
    mov bx, 7e00h
​
    mov al, 1
    mov ch, 0
    mov cl, 2
    mov dl, 0
    mov dh, 0
    mov ah, 2
    int 13h
    
    mov ax, 0
    push ax
    mov ax, 7e00h
    push ax
    retf
​
db 512 dup(0)
boot ends
​
code segment
    jmp short start                 ; 跳转到 start 执行程序
    
    option1: db '1) reset pc', 0
    option2: db '2) start system', 0
    option3: db '3) clock', 0
    option4: db '4) set clock', 0
​
    start:
        mov bp, 0
        mov bx, offset option1
        call printf
​
        mov bp, 160
        mov bx, offset option2
        call printf
​
        mov bp, 320
        mov bx, offset option3
        call printf
​
        mov bp, 480
        mov bx, offset option4
        call printf
​
        stop: jmp short stop        ; 死循环,暂停当前位置,不向下继续执行程序
    printf:
        mov ax, 0b800h
        mov es, ax
        mov si, 0
        mov ch, 0
        va: mov cl, cs:[bx + 07e00h]    ; 获取显示字符加上 7e00
        jcxz ok
        mov es:[si + bp], cl
        add si, 2
        inc bx
        jmp va
        ok: ret
db 512 dup(0)                       ; 定义 512 字节 0 数据,因为写入软盘是一个扇区 512字节,程序不够
code ends                           ; 512 字节,其它补充 0
​
; 写入软盘代码段
setup segment
    en:
        mov ax, code                ; 写入代码的段地址,任务程序在 code 段中
        mov es, ax
        mov bx, 0                   ; 偏移地址,从第一个字节开始写入数据
        
        mov al, 1                   ; 写入的扇区数,这里写入 1 个扇区
        mov ch, 0                   ; 磁道号
        mov cl, 2                   ; 扇区号,写入 2 扇区
        mov dl, 0                   ; 驱动器号,软驱从 0 开始,0:软驱A
        mov dh, 0                   ; 磁头号(面)
        
        mov ah, 3                   ; int 13h 的功能号(3 表示写扇区)
        int 13h
        
        mov ax, boot                ; 将引导程序 boot 写入 0道0面1扇区
        mov es, ax
        mov bx, 0
        
        mov al, 1
        mov ch, 0
        mov cl, 1
        mov dl, 0
        mov dh, 0
​
        mov ah, 3
        int 13h
        
        mov ax, 4c00h
        int 21h
setup ends
end en

        从上面给出的代码可以看出,除了将任务程序写入了2扇区,在1扇区添加了将2扇区数据读入到0:7e00处,并跳转到此处执行程序外,其它和上次的代码并没有区别。那么问题就来了,上次将程序默认读入到0:7c00处执行,并没有问题,程序正常执行,欢迎页面展示信息正常展示,为什么这次要将代码做出改动,将任务程序加载到0:7e00处执行,空出512字节的空间。我这样做的原因将会在下述开发的功能中给出说明。

        用户输入“1”、“2”、“3”、“4”对应不同功能,首先要处理的就是获取用户输入的信息,使用int 16h中断进行键盘缓冲区的读取。

; 获取键盘输入
input: mov ah, 0
       int 16h
​
       cmp al, '1'          ; 1:重新启动计算机,跳转到标号 reset 执行重新启动计算机程序
       je reset
       cmp al, '2'          ; 2:引导现有的操作系统,跳转到标号 system 执行引导现有操作系统程序
       je system
​
       jmp short input

        接下来就是开发重新启动计算机程序和引导现有操作系统程序功能了,首先来看重新启动计算机程序功能。

reset: mov ax, 0ffffh           ; 重新启动计算机,就是让程序跳转到 FFFF:0 单元处执行,这样就会将开机后的操作
       push ax                  ; 执行一遍,效果就是重新启动了计算机
       mov ax, 0
       push ax
       retf

        重启计算机是比较简单的,只要将程序跳转到FFFF:0单元处执行就可以了,下面就是开发引导现有操作系统程序功能了,这里也是我花了好长时间才完成的功能。

; 将c盘0道0面1扇区读入到内存0:7c00处,然后跳转到0:7c00处执行程序
system: mov ax, 0
        mov es, ax
        mov bx, 7c00h
        
        mov al, 1
        mov ch, 0
        mov cl, 1
        mov dl, 80h                 ; 硬盘C:80h
        mov dh, 0
        mov ah, 2
        int 13h
        
        mov ax, 0
        push ax
        mov ax, 7c00h
        push ax
        retf

        从代码上,并不复杂,就是将c盘0道0面1扇区读入到了0:7c00处,然后跳转到该处执行程序罢了,代码结构和boot代码段的结构是一样的,只是读取的数据和读入到内存的地址不一样罢了。

        我开始遇到的问题是,将c盘0道0面1扇区的数据读入到0:7e00处,然后跳转到该处执行程序,但是怎么也执行不成功,无法引导现有的操作系统,来回试了好多次都不行,所以就换了种方式,将任务程序读入到0:7e00处,将c盘0道0面1扇区读入到0:7c00处,此时就可以正常引导现有的操作系统了,这也是我为什么将代码做了调整,将任务程序写入到2扇区,再通过引导程序将2扇区的数据读入到0:7e00处执行的原因了,目的是空出7c00处的512字节给操作系统的引导程序使用。如果有哪位知道原因是什么,请不吝赐教。

        最后贴上完整的代码,执行,看一下效果。按下“1”:重新启动计算机;按下“2”:引导现有的操作系统。

boot segment
    mov ax, 0
    mov es, ax
    mov bx, 7e00h
​
    mov al, 1
    mov ch, 0
    mov cl, 2
    mov dl, 0
    mov dh, 0
    mov ah, 2
    int 13h
    
    mov ax, 0
    push ax
    mov ax, 7e00h
    push ax
    retf
​
db 512 dup(0)
boot ends
​
code segment
    jmp short start                 ; 跳转到 start 执行程序
    
    option1: db '1) reset pc', 0
    option2: db '2) start system', 0
    option3: db '3) clock', 0
    option4: db '4) set clock', 0
    
    start:
        mov bp, 0
        mov bx, offset option1
        call printf
​
        mov bp, 160
        mov bx, offset option2
        call printf
​
        mov bp, 320
        mov bx, offset option3
        call printf
​
        mov bp, 480
        mov bx, offset option4
        call printf
        
        ; 获取键盘输入
 input: mov ah, 0
        int 16h
​
        cmp al, '1'
        je reset
        cmp al, '2'
        je system
​
        jmp short input
​
        stop: jmp short stop        ; 死循环,暂停当前位置,不向下继续执行程序
    printf:
        mov ax, 0b800h
        mov es, ax
        mov si, 0
        mov ch, 0
        va: mov cl, cs:[bx + 07e00h]    ; 获取显示字符加上 7e00
        jcxz ok
        mov es:[si + bp], cl
        add si, 2
        inc bx
        jmp va
        ok: ret
    
    reset:
        mov ax, 0ffffh
        push ax
        mov ax, 0
        push ax
        retf
        
    system:
        ; 将c盘0道0面1扇区读入到内存0:7c00处,然后跳转到0:7c00处执行程序
        mov ax, 0
        mov es, ax
        mov bx, 7c00h
        
        mov al, 1
        mov ch, 0
        mov cl, 1
        mov dl, 80h                 ; 硬盘C:80h
        mov dh, 0
        mov ah, 2
        int 13h
        
        mov ax, 0
        push ax
        mov ax, 7c00h
        push ax
        retf
        
db 512 dup(0)                       ; 定义 512 字节 0 数据,因为写入软盘是一个扇区 512字节,程序不够
code ends                           ; 512 字节,其它补充 0
​
; 写入软盘代码段
setup segment
    en:
        mov ax, code                ; 写入代码的段地址,任务程序在 code 段中
        mov es, ax
        mov bx, 0                   ; 偏移地址,从第一个字节开始写入数据
        
        mov al, 1                   ; 写入的扇区数,这里写入 1 个扇区
        mov ch, 0                   ; 磁道号
        mov cl, 2                   ; 扇区号
        mov dl, 0                   ; 驱动器号,软驱从 0 开始,0:软驱A
        mov dh, 0                   ; 磁头号(面)
        
        mov ah, 3                   ; int 13h 的功能号(3 表示写扇区)
        int 13h
        
        mov ax, boot
        mov es, ax
        mov bx, 0
        
        mov al, 1
        mov ch, 0
        mov cl, 1
        mov dl, 0
        mov dh, 0
​
        mov ah, 3
        int 13h
        
        mov ax, 4c00h
        int 21h
setup ends
end en

        到此完成了功能1和功能2,下次再接着将功能3和功能4开发完。

新建了一个自己的个人网站,欢迎前来拍砖,地址:http://www.techxiaoz.xyz

公众号   

 

这篇关于汇编语言 — 课程设计2 — (二)重启计算机及引导现有操作系统的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!