为什么dos下的com文件都要org 0100h呢?为什么系统启动时要org 07c00h呢

本文解析了计算机启动过程中的关键内存地址FFFF0h与07C00h的作用及意义,介绍了BIOS如何初始化硬件并传递控制权给操作系统的过程。

这是因为 .com   载入内存后的起始偏址就是100h.   前面的100h字节是该程序的PSP 部分.   所以, 为了程序中对地址引用的正确,   必需加上org   100h语句。

-------------------------------------------------------------------------------------------------------------------------------------------------
FFFF0h与07C00h,这两个都是机器启动后默认访问的内存地址。曾经让我一度很晕,搞不清他们之间的关系。现在终于搞明白了,写到博客司上与大家分享。
首先要知道bios是用来初始化硬件的最底层的软件(然后才是操作系统),因此计算机启动后必须最先被执行。另外我们都知道CPU只能执行内存中的内容的,而一般内存中的数据是易失性的,断电之后内容就会消失。工程师的解决方法是:将存放bios的rom芯片与内存芯片统一编址(不明白的话去看看微机原理与接口的书就明白了)。这样就可以把存放bios的ROM芯片看作是数据永远不会消失不允许被更改的内存了
开机启动后默认的CS=FFFFh IP=0000h。这个地址就是bios的地址。这段内存空间很小,所以不能够容下操作系统等大型程序。
相对bios而言操作系统的功能更强大,更新也更快但是也需要更多的空间,通常放在硬盘中。但是如果没有bios的话,那么将会连硬盘都不能使用,又如何启动存放在硬盘中的操作系统呢?正是由于此,机器启动后自动执行bios使其它完成硬件初始化(这样包括硬盘在内的cpu以外的其他硬件设备就可以工作了)。bios完成硬件初始化的任务后,就要把权力移交给操作系统。
工程师进行了强制性的规定:到内存中的07c00h 处寻找系统的引导程序,即CS=0000h IP=7c00h。也就是说任何系统,他的引导程序都必须安排在07c00h开始的地方,否则就不能被正确的引导。当引导程序完成后我们就进入了Linux Windows等系统了。
后面为了调试方便,还可以吧org 07c00h改为0100h,生成 com文件就能直接在dos下运行。cx表示的是字符串的个数,10进制的,可以自行修改,boot sector的结束地址也是固定的,为0xAA55,呵呵,好玩
书中的代码如果要在DOS下运行,需要把org 07C00h改为org 0100h,这样做的目的是因为在DOS下,装载程序会事先创建一个称为程序段前缀(PSP)256字节的数据区,用来和被装载的程序通信,具体的细节请查验相关资料。而0100h刚好是256个字节的处,这也是代码段开始执行处。 
       说完程序的加载运行,让我们看看BIOS的10号中断处理子程序的显示功能。这里10号中断有很多子程序,书中用到了13子程序,此子程序就是显示字符串的,其中的参数如下:ES:BP=串地址;CX=串长度;DH=起始行;DL=起始列;BH=页号;BL=属性;AH=子程序编号,这里为13;这里BL是这样子定义的:闪烁 背景红 背景绿 背景蓝 高亮 前景红 前景绿 前景蓝(顺序为高字节到低字节)。这样BL=0Ch,二进制为:1100,由其定义可知为黑底高亮红字。 
转载自:http://www.cnblogs.com/wanghj-dz/archive/2011/05/12/2044062.html,原文可能有错误,这里略作修改
<think>嗯,用户的问题是关于Linux内核引导代码bootsect.s中,为什么使用0x7c00初始化DS寄存器而不是CS寄存器。首先,我需要回忆一下计算机启动过程中BIOS的作用以及实模式下的内存布局。根据引用[1]和[3],BIOS会把引导扇区的512字节加载到内存地址0x7C00处,然后跳转到那里执行。这候,CPU处于实模式,寻址方式是段寄存器左移4位加上偏移地址。 用户提到的是bootsect.s代码中的操作,具体是将DS寄存器设置为0x7c00(即BOOTSEG),而之后又移动代码到0x90000处。根据引用[2],代码一开始将DS设为0x7C00,然后通过rep movw将数据从0x7C00复制到0x9000段,之后跳转到0x9000执行。这候CS会被设置为0x9000,而DS在移动后也会被重新设置为0x9000。所以问题的关键在于为什么一开始设置的是DS而不是CS。 可能的原因是在实模式下,段寄存器的值决定了数据访问的基地址。在引导扇区刚被加载到0x7C00,代码开始执行的CS:IP应该是由BIOS设置的,即CS=0x0000,IP=0x7C00,或者CS=0x07C0,IP=0x0000,这两种组合都指向物理地址0x7C00。但代码中需要访问数据,比如复制自身到其他位置,需要使用DS来指定数据段的基地址,因此需要将DS设置为正确的段值,以便正确访问位于0x7C00处的数据。 另外,CS寄存器在跳转指令执行会自动改变。当执行jmpi指令到INITSEG(0x9000),CS会被更新为0x9000,而IP被设置为跳转目标的偏移。因此,在移动代码之前,设置DS为0x7C00是为了确保复制操作能够正确读取源地址的数据,而CS在跳转后才会被更新,所以初始阶段不需要手动设置CS,而是由跳转指令自动处理。 总结来说,DS需要显式设置是因为数据操作依赖于段寄存器,而CS在跳转由CPU自动更新。因此,在bootsect.s中初始化DS而不是CS是为了正确访问当前段内的数据,而CS会在代码跳转后自动调整。</think>在Linux内核引导代码$bootsect.s$中,使用$0x7c00$初始化DS寄存器而非CS寄存器,这是由x86实模式内存寻址机制和引导阶段代码自迁移需求共同决定的。具体原因可分为以下三个技术层面: 1. **物理地址计算规则** 在x86实模式下,内存地址计算遵循$物理地址 = 段寄存器值 \times 16 + 偏移地址$的规则。当BIOS将引导扇区加载到物理地址$0x7c00$,对应有两种等效的段地址表示方式: - $CS=0x0000$且$IP=0x7c00$ - $CS=0x07c0$且$IP=0x0000$ 此代码实际执行位置由$CS:IP$共同决定,但数据访问需要显式设置DS寄存器[^1][^3]。 2. **代码自迁移需求** $bootsect.s$的首要任务是将自身从$0x7c00$复制到$0x90000$(对应段地址$0x9000$)。使用: ```asm mov ax,#BOOTSEG ; BOOTSEG=0x07c0 mov ds,ax ; 设置源地址段 mov ax,#INITSEG ; INITSEG=0x9000 mov es,ax ; 设置目标地址段 rep movw ; 执行块传输 ``` 这里DS寄存器明确指向原始代码位置,确保正确读取源数据。CS寄存器此仍指向原始执行位置,直到通过`jmpi go,INITSEG`跳转后才更新[^2]。 3. **段寄存器分工特性** - CS寄存器由CPU自动管理,在跳转指令执行自动更新 - DS寄存器必须显式设置才能正确访问数据段 - 在代码迁移完成前,CS仍指向原始位置保证指令正常执行 - 迁移完成后通过`jmpi`指令原子化更新CS:IP到新位置[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值