【问题标题】:How do we use jump in assembly using these instructions?我们如何使用这些指令在汇编中使用跳转?
【发布时间】:2018-10-18 03:06:03
【问题描述】:

我知道在装配中跳转基本上是从一个位置到另一个位置。

假设我们有

804828f: 74 05            je XXXXXXX
8048291: e8 1e 00 00 00 call 80482b4 

根据这本书,我真正要做的只是将 0x05 添加到 8048291 产生 8048291,但我对这里的命令要求什么感到困惑。根据书,操作数 je 是 je 等于 / 0

然后我们有一个复杂的问题,我真的很难理解。

8048357: 72 e7                        jb XXXXXXXX
8048359: c6 05 10 a0 04 08 01 movb $0x1,0x804a010

据此,由于 e7 是 -25 的 1 位有符号表示, jb 转到地址 8048340。

那个。 . .对我来说毫无意义。 . .完全没有。一方面,如果某个东西是有符号的并且 1 字节不应该它的最大值只是 2?其次,如果某物是-25,那么为什么原点是8048340?如果没有 19 人,我们是如何从 59 人变成 40 人的?

我认为答案是:

我有一秒钟的想法,但是要从十六进制 25 中得到 19,我是否应该将 16 除以 25,取其余数 9,然后将 9 加到 10 中,即 1 在这种情况下代表什么?

不过,我真的迷失了有符号的单字节值。

【问题讨论】:

    标签: assembly x86 machine-code


    【解决方案1】:

    汇编中的分支是灵活的,从某种意义上说,您可以按照您想要的任何顺序排列代码块。您还可以通过跳转到同一块来合并分支。要存档此指令必须能够向前和向后跳转。下面的例子展示了向后跳跃的用法。

    073000:  bf 08 00 00 00          mov    edi, 0x8
    073005:  31 c0                   xor    eax, eax
    073007 <loop>:
    073007:  01 f8                   add    eax, edi
    073009:  83 ef 01                sub    edi, 0x1
    07300c:  75 f9                   jne    073007 <loop>
    07300e:
    

    向前跳转Opcode后面的数字为正数;向后跳操作码后面的数字是负数。在二进制世界中,数字的符号由其最高位决定。在示例中,十六进制 f9 是二进制 11111001,表示 -7(请参阅下文了解如何转换)。因为 hex(07300e) - 7 是 hex(073007),如果不设置会跳转到 073007 is ZF (即上例中减法后edi不为零)。

    在我看来,您对十六进制数字感到困惑。我将使用一些示例来展示如何将它们转换为十进制数。谷歌,你可以找到更多细节。

    Unsigned numbers:
    0x1234 =  1*16^3 +  2*16^2 + 3*16^1 +  4 = 4660 
    0x3420 =  3*16^3 +  4*16^2 + 2*16^1 +  0 = 13344 
    0x0A0B =  0*16^3 + 10*16^2 + 0*16^1 + 11 = 2571   (A is 10; B is 11)
    0x8000 =  8*16^3 +  0*16^2 + 0*16^1 +  0 = 37268
    0xFF7A = 15*16^3 + 15*16^2 + 7*16^1 + 10 = 65402  (F is 15)
    
    Signed numbers:
    0x1234 =   ; positive because 1 is smaller than 8
    0x3420 =   ; positive because 3 is smaller than 8 
    0x0A0B =   ; positive because 0 is smaller than 8
    0x8000 =   ; negative because 8 is NOT smaller than 8
    0xFF7A =   ; negative because F (15) is NOT smaller than 8
    
    Signed numbers:
    0x1234 = 4460  ; positive numbers are calculated like unsigned number
    0x3420 = 13344 ; positive numbers are calculated like unsigned number
    0x0A0B = 2571  ; positive numbers are calculated like unsigned number
    0x8000 = 32768 - 65536 = -32768 ; a simple way to calculate negative number
    0xFF7A = 65402 - 65536 = -134 ; a simple way to calculate negative number
    

    当第一个数字>= 8时,最高位为1,因此该数字为负数。

    65536 是 2^16。

    【讨论】:

    • 但是等等,f9 是在 07300C。 07300E 如何融入其中?
    • @The_Senate,请参阅下面彼得的回答。该数字不添加到跳转指令的地址(07300C);它被添加到跳转指令(07300E)之后的地址。
    • 更有意义。
    【解决方案2】:

    0x05 + 0x80482910x8048296。您似乎添加了 0,而不是 5。这是 5 字节 call 的条件跳转,如果设置了 ZF,则会被采用。 (http://felixcloutier.com/x86/Jcc.html)。

    x86 分支位移是相对于分支指令的结束,即下一条指令的开始。

    地址是十六进制的,而不是十进制的,即使它们在反汇编输出中不是以0x 开头的。请注意,804828f 包含 f 作为数字。位移是 1 个字节,而不是 1 位,因此范围为 -128 到 +127。如果 rel8 超出范围,则 rel32 跳转有不同的编码。

    Intel的手册解释了编码(2的补码扩展相对位移)和范围:https://www.felixcloutier.com/x86/jmp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多