《Linux0.11源码趣读》学习笔记day7

这次操作系统会对内存布局做最后一次大调整
《Linux0.11源码趣读》学习笔记day7_第1张图片这张图是上次学习时的内存布局
进入setup.s文件
现在程序跳转到了0x90200这个位置开始执行,这个位置的代码就位于setup.s的开头


start:
    mov ax,#0x9000  ; this is done in bootsect already, but...
    mov ds,ax
    mov ah,#0x03    ; read cursor pos
    xor bh,bh
    int 0x10        ; save it in known place, con_init fetches
    mov [0],dx      ; it from 0x90000.

这里又出现的int指令时触发BIOS提供的中断服务,就是调用显示服务相关的中断处理程序

代码中ah寄存器被赋值为0x13表示显示服务里具体的读取光标位置功能这个子服务
int 0x10执行完中断处理后返回时,会在dx寄存器中存储好光标的位置,高八位行号,低八位列号
《Linux0.11源码趣读》学习笔记day7_第2张图片

计算机加电自检后会自动初始化到文字模式,在这种模式下,一屏幕可以显示25行×80列

mov [0],dx 就是把这个光标位置存储在 [0] 这个内存地址处

这里需要注意,前面学过这个内存地址是偏移地址,最终的物理地址是要加上ds寄存器里存储的段基址
这里就可以知道,0x90000处存着光标位置,这在之后初始化控制台的时候会用到
操作系统最开始的时候会多次调用BIOS提供的现成程序

接下来的代码也是调用一个BIOS中断获取断点信息,然后存储在内存中的某个位置
代码放在下面了,逻辑和前面那段是一样的,注释里写得很清楚


比如获取内存信息。
; Get memory size (extended mem, kB)
    mov ah,#0x88
    int 0x15
    mov [2],ax
获取显卡显示模式。
; Get video-card data:
    mov ah,#0x0f
    int 0x10
    mov [4],bx      ; bh = display page
    mov [6],ax      ; al = video mode, ah = window width
检查显示方式并取参数
; check for EGA/VGA and some config parameters
    mov ah,#0x12
    mov bl,#0x10
    int 0x10
    mov [8],ax
    mov [10],bx
    mov [12],cx
获取第一块硬盘的信息。
; Get hd0 data
    mov ax,#0x0000
    mov ds,ax
    lds si,[4*0x41]
    mov ax,#INITSEG
    mov es,ax
    mov di,#0x0080
    mov cx,#0x10
    rep
    movsb
获取第二块硬盘的信息。
; Get hd1 data
    mov ax,#0x0000
    mov ds,ax
    lds si,[4*0x46]
    mov ax,#INITSEG
    mov es,ax
    mov di,#0x0090
    mov cx,#0x10
    rep
    movsb

这些代码执行完后,内存地址及其对应存储的信息就整理在下面的表格中
《Linux0.11源码趣读》学习笔记day7_第3张图片
保存好这些信息后,操作系统会执行cli命令关闭中断


cli         ; no interrupts allowed ;

因为后面要覆盖掉原本bios写好的中断向量表
即后面我们会破坏掉原有的中断向量表,写上自己的中断向量表。所以这个时候是不允许中断进来

接下来的代码:


; first we move the system to it's rightful place
    mov ax,#0x0000
    cld         ; 'direction'=0, movs moves forward
do_move:
    mov es,ax       ; destination segment
    add ax,#0x1000
    cmp ax,#0x9000
    jz  end_move
    mov ds,ax       ; source segment
    sub di,di
    sub si,si
    mov cx,#0x8000
    rep movsw
    jmp do_move
; then we load the segment descriptors
end_move:
    ...

这里又有了熟悉的rep指令,又是搬运内存中的内容
最终的结果是,把内存地址 0x10000 处开始往后一直到 0x90000 的内容,统统复制到内存的最开始的 0 位置
如下图所示
《Linux0.11源码趣读》学习笔记day7_第4张图片
现在的内存布局就变成了这样
《Linux0.11源码趣读》学习笔记day7_第5张图片
极客时间《Linux0.11源码趣读》学习笔记day7

你可能感兴趣的:(学习,linux,运维)