【问题标题】:What will be stored in the instruction pointer during a jmp instruction in x64 assembly?在 x64 汇编中的 jmp 指令期间,指令指针中将存储什么?
【发布时间】:2016-11-23 12:23:09
【问题描述】:

考虑汇编中的简单跳转指令 (jmp),其中目标是预定义的标签。

jmp destination

根据 Kip Irvine 的“x86 处理器的汇编语言”,当 CPU 执行无条件传输时,destination 的偏移量被移动到指令指针中。

有人能解释一下吗,因为我认为我们要跳转的地址必须移到指令指针中?

【问题讨论】:

  • “我们要跳转到的地址”和“目的地的偏移量(地址)”有什么区别?
  • 那么,存储在指令指针中的绝对地址是不是另一个值的偏移量?
  • IIRC IP中的值是codesegment的地址+jmp-label的地址。情况总是如此。所以在我们这个时代,这可能已经自动完成了,但在以前这意味着:地址,代码段开始的地方 + jmp 标签的地址(因此是单词偏移量)。
  • x86 是一种分段架构。虽然在长模式中分割被强制为平面模型,但机制仍然存在。因此,从技术上讲,ip/eip/rip 始终包含逻辑(段:偏移)地址的偏移部分。实际上,由于段从 0 开始,因此偏移量也是线性地址。不要与立即数中编码的偏移量混淆,这是添加到 IP 的当前值以达到目标的数字。
  • 您可以编辑您的问题以包含书中的引文吗?没有上下文,很难回答这个问题

标签: assembly x86


【解决方案1】:

我找到了你说的那一段:

4.5.1 JMP 指令

JMP 指令导致无条件传输到目标,由汇编器将其转换为偏移量的代码标签标识。语法是

JMP 目标

当 CPU 执行无条件传输时,目标的偏移量被移动到指令指针中,导致在新的位置继续执行。

你的困惑是可以理解的;这解释得不好。


首先,如果一条指令说jmp destination,那么它将设置指令指针等于destination。你是对的。

但指令行为与指令编码混淆。


jmp address 形式的指令在 x86 中使用 相对偏移 进行编码。偏移量是相对于地址紧跟jmp 指令的。

这可以编码为EB 后跟有符号字节偏移或E9 后跟有符号双字偏移。 (x86 中的整数是 little endian

例如,

00010000:  EB 01 CC 90

反汇编成

loc_10000:
    jmp loc_10003  ; EB 01
    int3           ; CC
loc_10003:
    nop            ; 90

00010000:  E9 01 00 00 00 CC 90

反汇编成

loc_10000:
    jmp loc_10006  ; E9 01 00 00 00
    int3           ; CC
loc_10006:
    nop            ; 90

请注意,这意味着以相同方式编写的指令在位于不同地址时可能具有不同的编码。例如,

00010000:  EB 02 EB 00 CC EB FD EB FB

反汇编成

loc_10000:
    jmp loc_10004  ; EB 02
    jmp loc_10004  ; EB 00
loc_10004:
    int3           ; CC
    jmp loc_10004  ; EB FD   (FD == -3)
    jmp loc_10004  ; EB FB   (FB == -5)

旁注:jmp 指令有几种不同的形式,但您所说的类型只能用相对偏移量编码。


无论如何,作者的意思是,对于像jmp destination 这样的指令生成机器代码的汇编程序,它必须将destination 转换为相对于jmp 指令末尾的字节偏移量。但是,大多数情况下,您无需担心此过程。你可以在你的程序集中定义一个标签并写jmp my_label,汇编程序会为你处理一切。

【讨论】:

  • 当他们在那里说“偏移”时,它们的意思是“从 CS 段基数偏移”(通常是 16 位代码之外的 0),而不是机器编码中使用的相对位移。 x86 中的所有地址都称为偏移量,除了包含段和偏移量的“远指针”。例如the jmp ptr16:32 具有直接绝对地址的表单。
【解决方案2】:

考虑一下这台假机器

address:    bytes:       comment:
0x0004      01 20 00     ; jmp destination  ; here ip = 0x0004
0x0007      ?? repeated 0x19 times
destination:
0x0020      02           ; hlt  ; here ip = 0x0020

从这个来源编译:

    .code
    org  0x0004
    jmp destination
    org  0x0020
destination:
    hlt

所以这里的符号destination 表示.code 部分中的绝对地址0x0020(我不会给出任何特殊含义,但是您可以根据需要想象任何复杂的构造,例如参见16b 中的段寄存器x86 的模式)。

如果代码为 0x01 jmp 的指令是“near”,则只使用该绝对地址的偏移量,在这个简单的假示例中为 0x0020。

您仍然可以在 CPU 上使用 jmp 的其他变体,例如“相对”0x03 jmp rel8 能够从当前 ip 跳转 -128..+127 字节,或“远”0x04 jmp bank/segment:offset,这不仅会设置ip,还会设置一些银行/细分机制。

所以“偏移”这个词指向segment:offset 寻址的时代,x86 上的完整指令指针是cs:ip,而不仅仅是ip。 (cs = 代码段)

在现代 32/64b x86 操作系统中,您通常不必触摸 cs,并且仅使用 32/64b 平面虚拟内存映射内的偏移量,然后“地址”与“地址偏移量”具有相同的含义.

【讨论】:

  • 当 1) 他已经提到 x86 和 2) x86 中不存在绝对直接跳转时,我看不到创建像上面那样的假架构来回答这个问题的价值
  • @user1354557 我不得不承认......我不能在我的脑海中保持一个sh * t(或者也许只有我能),所以每当我做x86时,我必须模仿我所做的一切查看旧代码,或重新阅读说明指南。这次我很懒,所以我宁愿添加一些假机器来解释“偏移”这个词在这种情况下的含义。 (顺便说一句,JMP m16:32 非常接近它,除了完全不同和间接的东西)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
  • 2011-11-09
相关资源
最近更新 更多