x86 中的 jmpl 指令是什么?

Jiw*_*won 6 x86 assembly gnu-assembler att

x86 汇编设计有指令后缀,如l(long), w(word), b(byte)
所以我认为这jmpllong jmp

但是当我编译它时它的工作很奇怪。
见下面的例子。

测试1:组装

main:
  jmp main
Run Code Online (Sandbox Code Playgroud)

测试1:编译结果

eb fe     jmp 0x0804839b <main> 
Run Code Online (Sandbox Code Playgroud)


测试2:组装

main:
  jmpl main # added l suffix
Run Code Online (Sandbox Code Playgroud)

测试2:编译结果

ff 25 9b 83 04 08   jmp *0x0804839b
Run Code Online (Sandbox Code Playgroud)


与Test1相比,Test2的结果出乎意料。
我认为它应该与Test1一样编译。


问:
jmpl什么不同的指令在8086的设计?
(根据这里jmpl在 SPARK 中意味着 jmp 链接。是这样的吗?)

...或者这只是 gnu 汇编程序上的错误?

Joh*_*ica 6

你已经成为 AT&T 语法可怕的受害者。

x86汇编设计有指令后缀,如l(long)、w(word)、b(byte)。

不,它没有。AT&T 语法的可憎之处就是这样。
在理智的英特尔语法中,没有这样的后缀。

jmpl 有什么不同。

是的,这是到绝对地址的间接跳转。ljmpgnu 语法中-near- 跳转到-long- 地址是-far- 跳转。
跳转的默认值是近跳转,到相对地址。
请注意,此跳转的 Intel 语法为:

jmp dword [ds:0x0804839b]  //note the [] specifying the indirectness.
//or, this is the same
jmp [0x0804839b]
//or
jmp [main]
//or
jmp DWORD PTR ds:0x804839f  //the PTR makes it indirect.
Run Code Online (Sandbox Code Playgroud)

我更喜欢[], 以突出间接性。

它并不会跳转到0x0804839b,但读取来自指定地址的DWORD,然后跳转到这个DWORD指定的地址。在 Intel 语法中,间接性是明确的。

当然,您打算直接跳转到 0x0804839b(又名 main:),这是通过以下方式完成的:

Hm, most assembler do not allow absolute far jumps!  
It cannot be done.
Run Code Online (Sandbox Code Playgroud)

另请参阅:如何在 MASM 中编写远绝对 JMP/CALL 指令?

近/远相对跳转(几乎)总是更好,因为当您的代码更改时它仍然有效,长跳转可能变得无效。此外,较短的指令通常更好,因为它们在指令缓存中占用的空间较少。汇编器(在 Intel 模式下)将自动为您选择正确的 jmp 编码。

SPARC
这是一个与 x86 完全不同的处理器。来自不同的制造商,使用不同的范例。显然,SPARC 文档与 x86 文档无关。

正确的文档在jmp这里。

https://www.felixcloutier.com/x86/jmp

请注意,英特尔没有为 jmp 的相对和绝对形式指定不同的语法。这是因为 Intel 希望汇编器始终使用短(相对)跳转,除非目标太远,在这种情况下使用远跳转(AT&T 语法中的 jmpl)。
这样做的好处是汇编器会自动为您使用正确的跳转。

强制 gnu 恢复理智
您可以使用

 .intel_syntax noprefix    <<-- as the first line in your assembly
 mov eax,[eax+100+ebx*2] 
 ....
Run Code Online (Sandbox Code Playgroud)

为了让 gnu 使用 Intel 语法,这将使事情回到 Intel 设计的方式,并远离gnu 使用的PDP7 语法

  • 所有这些对 GAS 和 AT&amp;T 语法的憎恨似乎都是不必要的。它实际上有许多很棒的功能(它的伪操作是最好的,例如 nop 对齐)。它还要求您明确操作数大小,并且没有任何令人困惑的“DWORD PTR FLAT”内容。 (2认同)

Pet*_*des 6

操作数大小后缀l意味着间接jmp,与 不同的是,calll main后者仍然是相对的近调用。 这种不一致在 AT&T 语法设计中纯粹是疯狂的。

(并且由于您将它与类似 的操作数一起使用main,因此它变成了内存间接跳转,从中加载数据main并将其用作新的 EIP 值。)

您永远不需要使用助记符,您可以并且应该使用操作数来jmpl指示间接跳转*。比如jmp *%eax设置 EIP = EAX,或者jmp *4(%edi, %ecx, 4)索引跳转表,或者jmp *func_pointer. jmpl所有这些中的使用都是可选的。

您可以使用jmpw *%ax将 EIP 截断为 16 位值。组装起来66 ff e0 jmpw *%ax


比较什么是callq指令?retq和ret 有什么区别?,这只是操作数大小后缀的行为就像您预期的那样,与 plaincall或 plain相同ret。但又jmp不同。


半相关:AT&T 语法中的远跳转或调用(到新的 CS:[ER]IP)是 ljmp / lcall。这些是非常不同的。


GAS 接受等同jmpl mainjmpl *main. 它只是警告而不是错误

$ gcc -no-pie -fno-pie -m32 jmp.s 
jmp.s: Assembler messages:
jmp.s:3: Warning: indirect jmp without `*'
Run Code Online (Sandbox Code Playgroud)

然后将其拆开看看我们得到了什么objdump -drwC a.out

08049156 <main>:                                          # corresponding source line (added by hand)
 8049156:       ff 25 56 91 04 08       jmp    *0x8049156    # jmpl main
 804915c:       ff 25 56 91 04 08       jmp    *0x8049156    # jmp  *main
 8049162:       ff 25 56 91 04 08       jmp    *0x8049156    # jmpl *main

08049168 <foo>:
 8049168:       e8 fb ff ff ff          call   8049168 <foo> # calll foo
 804916d:       ff 15 68 91 04 08       call   *0x8049168    # calll *foo
 8049173:       ff 15 68 91 04 08       call   *0x8049168    # call  *foo
Run Code Online (Sandbox Code Playgroud)

如果我们在源代码中替换lwith ,然后构建 without (使用默认的),我们会得到同样的结果。包括关于失踪的相同警告。但反汇编在每条指令上都有明确的指示。(除了我添加的相对直接,它在反汇编中使用助记符。)q-m32-m64*jmpqcallqjmpjmp

就像 objdump 认为 32 位是 32 位和 64 位模式下 jmp/call 的默认操作数大小,因此它希望始终q在 64 位中使用后缀,但在 32 位模式中将其隐式保留。不管怎样,这只是隐式/显式大小后缀之间的反汇编选择,对于编写源代码的程序员来说并没有什么奇怪的。


其他 AT&T 语法汇编器:

  • Clang 的内置汇编器确实拒绝jmpl main,要求jmpl *main.

    $ clang -m32 jmp.s
    jmp.s:3:8: error: invalid operand for instruction
      jmpl main
           ^~~~
    
    Run Code Online (Sandbox Code Playgroud)

    calll main是相同的call maincall *main并且calll *main都被接受用于间接跳转。

  • YASM 的 GAS 语法模式汇编jmpl main为近乎相关的 jmp,例如jmp main! 所以它不同意 gcc/clang 关于jmpl暗示间接的观点。(很少有人在 GAS 模式下使用 YASM;如今,对于像 AVX512 这样的新指令,它的维护并没有跟上 NASM 的步伐。我喜欢 YASM 对于长 NOP 的良好默认设置,但除此之外我会推荐 NASM。)