好吧,这是一个难以处理的问题,因为它处理了很多硬件细节,所以我想把它放到EE.SE,但是主要关注的是编程,所以我决定坚持在这里 .
我最近得到了一个很大的怀旧感(以及重新回到CPU内在函数),所以我决定自制一个8086微电脑板 . 当然,我熟悉x86程序集(在某种程度上,你会看到)并且我已经知道如何将我的代码放到计算机主板上,让我们来解决实际问题 . 为了获得通知,我正在使用NASM,尽管我还没有完全掌握它的语法 .
显然,在模式下工作的8086(实模式尚未被称为实模式)在开始时将最初的1,024个字节分开为255 2 2字节中断向量,因此实际指令列表从 0x3FF
开始 .
这里的问题是因为系统的内存分割的怪癖,以及我可能也在编写BIOS,从系统的方面来看 . 是否必须设置段寄存器,如果是,我如何确定放在那里的内容?假设我在我的代码存储中使用EEPROM或某种形式的Flash,所以我有类似的东西:
section .text
org 0x0000
; Interrupt vectors reserved
ivt: times 1024 db 0
main:
cli ; Clear out interrupts because no addresses are defined yet
; Problems HERE.
; Set up interrupt addresses
我知道这可能是非常糟糕的,很可能是明显错误的语法,但它说明了我正在努力做的事情 . 我是否必须通过 mov CS, blahblahblah
等手动设置分段寄存器,如果是这样,我如何确定代码体中不同段/节的地址?
这个问题的 Headers 提到了这样一个事实,虽然我已经做了很多谷歌搜索,但我不能在我的生活中找到8086的操作系统编程的参考 . 我能找到的所有资源假设我正在编写一个已经存在的系统,其中已经设置并计算出中断向量和段等,而我正在尝试制造一个从头开始执行所有操作的仿冒微控制器 .
3 回答
在我看来,你问的是在哪里放置启动代码 .
当您启动机器时,直接退出重置,
CS
(代码段)具有以下值:选择器:
0ffffh
base:
0ffff0h
和
IP
(指令指针),其值为00000h
.添加
CS.base
和IP
会给出0ffff0h
的起点 .请注意,这不会给您留下太多工作空间 - 在内存不足之前只有16个字节,但这足以让您远程跳转到您希望放置代码的任何位置 .
8086使用非常简单的表单分段,其中每个内存引用都基于四个段寄存器之一
CS
,DS
,SS
或ES
. 这意味着无论是否在现代英特尔处理器中称为实模式分段,分段始终用于每次内存访问 .CS
寄存器确定代码段的基础 . 所有指令提取都在此段中完成,位于IP
寄存器提供的偏移处 . 由于Nathan Fellman的回答表明CS:IP
在处理器初始化期间加载了FFFF:0000
,给出了FFFF0h
的说明物理地址,因此您也可能还需要在中断向量表的物理地址空间的开头有一些表单存储器 .在哪里找到其他任何东西都取决于你 . 您需要加载
DS
寄存器,使其指向要存储大部分数据的位置,因为大多数内存操作数默认使用此段 . 您'll probably also want to have a stack so you' ll还需要使用合适的值加载SS
(和SP
) . 如果需要,可以将相同的值加载到SS
中作为DS
.ES
寄存器不需要加载任何特定值,因为只有少数指令隐式使用它(MOVS
,SCAS
,CMPS
) . 您可能希望它可以自由地用作"extra"临时段寄存器来访问除CS
,DS
或SS
所引用的内存区域之外的内存区域 .请注意,假设您拥有真正的Intel 8086或80186处理器 . 如果您实际上只有80286或更高版本的处理器,您只想在实模式下使用,那么起始地址将会有所不同 . 如果你有某种克隆8086处理器,你应该查阅它的数据表,看看它是否也做了不同的事情 .
对于无操作系统,无BIOS的8086编程,您可以将某些BIOS源代码用作有 Value 的信息源 . 像这个:
CLI
mov ax,#0xfffe
mov sp,ax
xor ax,ax
mov ds,ax
mov ss,ax
...
也可以看看:
Combined Volume Set of Intel® 64 and IA-32 Architectures Software Developer’s Manuals
9.1.4 First Instruction Executed