所以,正如问题所述,intel的8086中CS和IP寄存器的目的是什么?
我找到了这个解释:
代码段(CS)是一个16位寄存器,包含有处理器指令的64KB段的地址。处理器使用CS段访问所有由指令指针(IP)寄存器引用的指令。不能直接更改CS寄存器。在进行far jump、far call和far return指令时,CS寄存器会自动更新。
对于IP,它的解释如下:
指令指针(IP)是一个16位寄存器。
我不太理解这基本上意味着什么,如果有人能提供更“生动”的解释,那就太好了 :)
物理地址由两个部分计算得出。 i)段地址。 ii)偏移地址。 CS(代码段寄存器)用于寻址内存中的代码段,即存储代码的内存位置。IP(指令指针)包含在内存中代码段的偏移量。因此,CS:IP用于指向代码在内存中的位置(即计算物理地址)。
由于指令指针(IP)为16位,这意味着您只能有64k条指令(2^16),即使在80年代也不多。因此,为了扩展地址空间,你需要第二个寄存器来寻址64k块。你可以将 cs:ip
视为一个32位寄存器,能够寻址2^32字节...即4G,这是使用32位地址的处理器所提供的。 8086使用20位地址,因此可以访问1M内存。
接下来要执行的指令是存储在内存地址等于:
16 * CS + IP
尽管寄存器只有16位宽度,但是这允许寻址20位内存(同时也创造了两种编码大多数地址的不同方式)。
CS
的效果类似于其他段寄存器的效果。例如,DS
通过 16*DS
增加数据访问(如果没有指定另一个段寄存器)。
CS
修改 CS 的指令包括:
不能像其他段寄存器一样使用 mov
来修改 CS。尝试使用 GNU GAS 2.24 的标准标识符对 CS 进行编码,如果您编写以下内容,则编译器不会报错:
mov %ax, %cs
执行时会导致无效代码异常。
为了观察CS的影响,请按照这里https://dev59.com/HWEh5IYBdhLWcg3wwly8#32483545所述,在引导扇区中添加以下内容并在QEMU中运行。
/* $1 is the new CS, $1f the new IP. */
ljmp $1, $after1
after1:
/* Skip 16 bytes to make up for the CS == 1. */
.skip 0x10
mov %cs, %ax
/* cs == 1 */
ljmp $2, $after2
after2:
.skip 0x20
mov %cs, %ax
/* cs == 2 */
IP(指令指针)
每当执行一条指令时,IP会自动增加该指令的编码长度:这就是程序向前移动的原因!
IP由相同的修改CS的指令修改,以及那些指令的非far版本(更常见的情况)。
无法直接观察IP,因此更难操作它。有关替代方案,请查看以下问题: 直接读取程序计数器
$after
不是相对的,而是绝对的,例如来自https://c9x.me/x86/html/file_module_x86_id_147.html的`EA cd`编码,GNU Gas根据要使用的确切指令编码正确地确定了重定位类型。 我建议从反汇编中确认这一点。 - Ciro Santilli OurBigBook.com由于8086处理器使用20位寻址,我们可以访问1MB的内存,但是8086的寄存器只有16位,因此为了从内存中访问数据,我们需要将代码段寄存器和指令指针寄存器中的值相结合生成物理地址。这是通过将CS的值向左移动4位,然后与IP的值相加来完成的。
示例:
CS的值为1234Hex(十六进制)
IP的值为5678Hex
现在将CS的值左移4位后,其值为12340Hex,然后再与IP的值相加得到179B8Hex,这就是物理地址。
IP寄存器 - IP代表指令指针。它的功能与其他微处理器中的PC(程序计数器)相同,即指向下一个指令,以便BIU单元获取并提供给EU单元。