Bootsect代码详解

本文详细分析了Bootsect代码中的关键汇编指令`movsw`,探讨了Intel 80386指令集中的字符串指令`MOVS`及其与`REP`前缀的配合使用,涉及方向标志位DF、内存块传输以及实地址模式下的段间跳转`jmpi`。同时,文章解释了在内存地址0x07C0:0000到0x9000:0000之间的代码复制过程,并讨论了堆栈操作中SS和SP寄存器的设置,为理解 bootsect 操作系统引导加载器的工作原理提供了深入见解。

首先来看第一条关键汇编指令:rep movw

关于这个movw指令,查了网上很多说法,这里我调查的情况是:在INTEL 80386的数据手册中没有movw指令,只有movsw指令。

按照之前学习的内容,bootsect使用的是intel的as86汇编器编译,as86的mov语法是mov Destination Source;从第47行的mov语法看确实是as86汇编器语法。而movw是GNU as汇编器(AT&T)支持的指令关键字。显然,这里是书中的一个错误。但是,这段程序似乎可以在BOCHS中编译通过,此处是个关于AS86与AT&T汇编器相关知识的一个入口,暂且存疑了。

 

关于movsw可以参考下面80386手册中的解释:

MOVS是个字符串指令,将ESI指向的字符串元素移动到EDI指向的位置处。movsb/movsw/movsd分别可以对字节、字和双字进行操作。目的段寄存器不能被段覆盖前缀覆盖,源段寄存器可以被覆盖。【段覆盖前缀】。即目的段寄存器只能使用ES,不能使用其他的寄存器代替。源段寄存器是DS,可以被替代为其他的段寄存器。

movs指令和REP前缀一块使用,实现的是内存到内存的块传输。该操作需要初始化ECX、ESI和EDI寄存器。ECX指定了具体的字节、字和双字个数。

第三点是DF标志位,方向标志位,当DF=0时,复制操作的方向是从第一个元素到最后一个元素,步长为+1;当DF=1时,复制操作是反方向进行的,步长为-1。CLD指令会将DF置为0,STD指令将DF置为1。

说明:具体的段覆盖前缀参考下图:

i386有些默认的段寄存器是不能被替换的:

比如上文提到的ES用于目的字符串,SS用于堆栈指令,CS用于指令获取操作等。

此处分割线。

继续向下分析代码:

实地址模式下内存地址0x07C0:0000处的代码已经被成功的复制到内存地址0x9000:0000处。下面再执行后续代码,CPU就直接跳转到0x9000这个段地址处了。jmpi(JMP intersegment)是实地址模式下的段间跳转指令。该指令执行后CS==0x9000,IP==go。因此,后续操作的ds es和ss段皆设置成了0x9000。

这里需要重点说明下此处的堆栈操作,正如上图书中所示,后续牵扯到了出入栈和call调用操作,需要设置堆栈。堆栈是通过SS:SP来确定内存地址的,SS已经被设置为0x9000,那么SP应该设置在哪呢?

答案:根据上篇文章的内存map可知,0x90200开始将会存放大概4个扇区即(4*512字节)的setup可执行代码,加上bootsect的512字节也就是0x90A00,考虑到堆栈是sp指向堆栈顶部,所以SP要指向大于(0x90A00+堆栈大小)地址即可。这里选择了0x9ff00。堆栈大小为0x9ff00-0x90A00=0xF500=61.25K。bootsect在内存中的搬移,以及搬移后设置SS:SP的操作过程就解析到这里,后面一篇文章将继续分享从磁盘2/3/4/5扇区读取setup的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值