从0创建一个OS (七) 汇编中的段

本节将学习16bit模式的段结构

关键字:段

目标:学习如何在16bit模式下寻址

如果你对段已经很熟悉了,那么你可以跳过本节.

理论基础

从0创建一个OS (四) 电脑存储的组织形式一节中我们利用org完成了对booot sector的全局基址定义,那是我们第一次在本系列博客中接触到段的概念.

段寄存器中存储的为段地址,从第一代8086机问世以来,之后每一代计算机的基础段寄存器一直没有变化,有以下4个:

cs: code segment 代码段
ds: data segment 数据段
ss: stack segment 栈段
es: extented segment 扩展段

其中ds常和es搭配使用,用于复制字符串.
这4个寄存器无法直接使用类似于mov cs, 0xcd的语句赋值,必须借助于中间寄存器,如:

mov ax, 0xcd
mov cs, ax

 

注意!这4个寄存器在隐式地被CPU调用,用来寻址,所以在改变这4个寄存器的值之前,你必须明白自己在做什么,会不会影响到CPU接下来的寻址.

16bit模式下的物理地址计算方法如下:
物 理 地 址 = 段 地 址 < < 4 + 偏 移 地 址 物理地址 = 段地址 << 4 + 偏移地址 =<<4+
例如,假设当前的ds的值为0x4d,那么[x20]表示的物理地址为:
0x4d0 + 0x20 = 0x4f0

至于为什么要将段地址左移4位呢?本文不做解释,可以给大家提供一个线索,第一代8086的数据总线有20位.

源码

废话不多说,上代码

注意,这次我们并没有使用[org 0x7c00]
文件名: boot_sect_segmentation.asm

; =====================================================================
; 本程序做了4个尝试
; 1、直接打印标签the_secret指向的值
; 2、对段寄存器ds赋值0x7C0,隐式调用ds,并打印the_secret指向的值
; 3、直接显式调用段寄存器es,看看能否使用[es:the_secret]完成对the_secret的打印
; 4、对段寄存器es赋值0x7C0,显式调用es,并打印the_secret指向的值
; =====================================================================

mov ah, 0x0e ; 准备使用0x10号中断的打印字符功能

mov al, [the_secret]
int 0x10 ; 很明显这样是打印不出来东西的,本系列博客的第二节就尝试过了

; 给数据段段寄存器赋值,0x7C0,是不是很眼熟?
mov bx, 0x7C0
mov ds, bx

; 这里的[the_secret]其实是[ds:the_secret]
mov al, [the_secret]
int 0x10

; 显式调用es作为the_secret的段地址存储器
mov al, [es:the_secret]
int 0x10

; 向es赋上我们熟悉的值0x7C0
mov bx, 0x7C0
mov es, bx
mov al, [es:the_secret]
int 0x10

jmp $

the_secret:
    db "X"

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

 

实验结果

在这里插入图片描述

总结

发现尝试2和尝试4打印成功,即隐式调用ds和显式调用es成功,说明CPU在寻址时默认使用的段寄存器为DS.

posted @ 2020-11-18 17:02  EwanHai  阅读(117)  评论(0编辑  收藏  举报