【问题标题】:What is the purpose of CS and IP registers in Intel 8086 assembly?英特尔 8086 程序集中 CS 和 IP 寄存器的用途是什么?
【发布时间】:2013-07-20 13:44:12
【问题描述】:

那么,正如问题所述,英特尔 8086 中 CS 和 IP 寄存器的用途是什么

我找到了这个解释:

代码段 (CS) 是一个 16 位寄存器,包含处理器的 64 KB 段地址 指示。处理器使用 CS 段来访问所有引用的指令 指令指针(IP)寄存器。 CS 寄存器不能直接更改。 CS寄存器 在远跳转、远调用和远返回指令期间自动更新。

这适用于 IP:

指令指针 (IP) 是一个 16 位寄存器。

我不太明白这基本上意味着什么,所以如果有人可以提供更“生动”的解释,那就太好了:)

【问题讨论】:

    标签: x86 intel x86-16


    【解决方案1】:

    物理地址由两部分计算得出。 i) 段地址。 ii) 偏移地址。 CS(代码段寄存器)用于寻址存储器的代码段,即存储器中存储代码的位置。 IP(指令指针)包含内存代码段内的偏移量。因此 CS:IP 用于指向内存中代码的位置(即计算物理地址)。

    【讨论】:

      【解决方案2】:

      由于指令指针 (IP) 是 16 位的,这意味着您只能拥有 64k 条指令 (2^16),即使在 80 年代也不多。因此,为了扩展地址空间,您需要使用第二个寄存器来寻址 64k 块。您可以将cs:ip 一起视为一个 32 位寄存器,然后它能够​​寻址 2^32 字节......即 4G,这是您在使用 32 位地址的处理器上获得的。 8086 使用 20 位地址,因此您可以访问 1M 的内存。

      【讨论】:

      • CS 在哪里使用?我读了一点关于段和偏移的内容,我可以说我对段/偏移机制有所了解。
      • 我扩展了我的问题:CS 在哪里使用?我读了一点关于段和偏移的内容,我可以说我了解段/偏移机制。但是,代码段寄存器在哪里使用?据我所知,有数据段、堆栈段、额外段和提到的代码段?由于 CS 与 IP 寄存器“配对”,并且使用它的 4 位作为偏移量,其他寄存器是否也与 IP 寄存器配对,或者这 4 个段寄存器中的每一个都有自己的偏移量寄存器?
      • 每次处理器(从 IP)获取一条新指令时,都会隐式使用 cs。 CS指向你程序的代码段,下一条指令所在的物理地址是透明汇编的。同样,每次访问驻留在 ds 中的数据(mov ax, [1234] -- 1234 隐含地以 ds 为前缀)时。你不能用 CS 做很多事情,但是当你跳远时它会被使用。
      • cs:ip 作为一个 32 位寄存器,然后能够寻址 2^32 字节。这是错误的。即使在实模式下的 32 位处理器上,CS:IP 仍然只能使用 20 位进行寻址。(从技术上讲,在 286 或 386+ 上,CS:IP 能够寻址 0 到 0x10FFEF,因为 0xFFFF:0xFFFF=( 0xFFFF
      • 同意迈克尔·佩奇的评论。根据其定义,16 位 CS:IP 最多可寻址 0x10FFEF。 CS地址的起始地址是固定的,就是它的值乘以0x10。
      【解决方案3】:

      接下来要执行的指令是内存地址等于:

      16 * CS + IP
      

      尽管寄存器只有 16 位宽,但它允许寻址 20 位内存(并且它还创建了两种不同的方式来对大多数地址进行编码)。

      CS 的作用与其他段寄存器的作用类似。例如,DS 将数据访问(不指定另一个段寄存器)增加16 * DS

      CS

      修改CS的指令为:

      • ljmp(远跳)
      • lcall(far call),将ipcs压入栈,然后far跳转
      • lref(远返回),与远调用相反
      • int,从中断向量表中读取IP/CS
      • iret,它反转一个 int

      CS 不能像其他段寄存器一样被mov 修改。尝试使用 CS 的标准标识符对其进行编码,如果您编写,GNU GAS 2.24 不会抱怨:

      mov %ax, %cs
      

      执行时导致无效代码异常。

      要观察 CS 的效果,请尝试将以下内容添加到引导扇区并在 QEMU 中运行它,如下所述https://stackoverflow.com/a/32483545/895245

      /* $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 的相同指令修改,以及这些指令的非远版本(更常见的情况)。

      IP 不能直接观察,所以比较难玩。检查此问题以获取替代方案: Reading Program Counter directly

      【讨论】:

      • 在您提供的示例中,$1$2 可以是任意(有效)值吗?由于$after1$after2 是当前IP 的相对值,所以不要$1$2 必须为0 才能正确跳转(如果段寄存器不为0,则16*CS+IP 不会' t 匹配标签,因为$after 已经说明了差异)?
      • @tartaruga_casco_mole(好昵称)我认为$after 不是相对的,而是绝对的,例如来自c9x.me/x86/html/file_module_x86_id_147.htmlEA cd 编码和GNU Gas 根据要使用的确切指令编码正确决定重定位类型。我建议通过反汇编确认这一点。
      【解决方案4】:

      由于 8086 处理器使用 20 位寻址,我们可以访问 1MB 的内存,但 8086 的寄存器只有 16 位,所以要从内存中访问数据,我们将代码段寄存器和指令指针寄存器中存在的值结合起来要生成物理地址,可以通过将 CS 的值移动 4 位来完成 向左,然后将其添加到值 IP

      示例:

      CS 的值为 1234Hex(十六进制)

      IP 值为 5678Hex

      现在左移 4 位后 CS 的值是 12340Hex 然后加上 IP 值后它是 179B8Hex 即物理地址

      【讨论】:

        【解决方案5】:

        在汇编程序文本中编写 .code 后,该 .code 将指向 cs 值。文件中稍后或更早的任何命令都将按照 cs:ip 进行处理,其中 ip 是来自 cs 的偏移值。

        当然,你要记住,汇编编译器会先将文本转换成机器码指令。

        【讨论】:

          【解决方案6】:

          IP 寄存器 - IP 是指令指针。它的作用与其他微处理器中的PC(程序计数器)相同,都是指向BIU单元要取的下一条指令送入EU单元。

          【讨论】:

            猜你喜欢
            • 2011-08-15
            • 1970-01-01
            • 1970-01-01
            • 2020-10-23
            • 2017-07-02
            • 2015-02-24
            • 2021-02-27
            • 2011-07-16
            相关资源
            最近更新 更多