gnu程序集中.byte汇编程序指令的用途是什么?

问题描述 投票:11回答:4

在浏览一些具有内联汇编的C代码时,我遇到了.byte(开头有一个Dot)指令。

在检查Web上的程序集引用时,我发现它用于在内存中保留一个字节。

但是在代码中,声明之前没有标签。所以我想知道什么是使用未标记的.byte指令或任何其他数据存储指令。

对于例如如果我编码.byte 0x0a,我该如何使用它?

assembly inline-assembly
4个回答
7
投票

有几种可能性......这里有一对我可以想到的最爱:

  1. 您可以相对于.byte指令之后的标签访问它。例: .byte 0x0a label: mov (label - 1), %eax
  2. 根据程序的最终链接布局,也许.byte指令将作为代码执行。通常你也会在这种情况下有一个标签,但......
  3. 有些汇编程序不支持为操作数大小等生成x86指令前缀。在为这些汇编程序编写的代码中,您经常会看到如下内容: .byte 0x66 mov $12, %eax 使汇编程序发出您想要的代码。

2
投票

这是内联汇编的示例:

#include <stdio.h>
void main() {
   int dst;
   // .byte 0xb8 0x01 0x00 0x00 0x00 = mov $1, %%eax
   asm (".byte 0xb8, 0x01, 0x00, 0x00, 0x00\n\t"
    "mov %%eax, %0"
    : "=r" (dst)
    : : "eax"  // tell the compiler we clobber eax
   );
   printf ("dst value : %d\n", dst);
return;
}

(见compiler asm output and also disassembly of the final binary on the Godbolt compiler explorer。)

您可以用.byte 0xb8, 0x01, 0x00, 0x00, 0x00替换mov $1, %%eax,运行结果将是相同的。这表明它可以是一个可以表示某些指令的字节,例如移动或其他指令。


2
投票

最小的可运行示例

无论你身在何处,.byte都会吐出字节。无论是否有标签指向该字节,都无关紧要。

如果您恰好位于文本段中,那么该字节可能会像代码一样运行。

Carl提到了它,但是这里有一个完整的例子让它更进一步:true的Linux x86_64实现,其中引入了nop

.global _start
_start:
    mov $60, %rax
    nop
    mov $0, %rdi
    syscall

生成完全相同的可执行文件:

.global _start
_start:
    mov $60, %rax
    .byte 0x90
    mov $0, %rdi
    syscall

因为nop被编码为字节0x90

一个用例:新指令

一个用例是将新指令添加到CPU ISA时,但只有非常边缘版本的汇编程序才会支持它。

因此,项目维护人员可以选择直接内联字节,以使其在旧的汇编程序中可编译。

例如,使用类似的.inst指令查看Linux内核上的Spectre变通方法:https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/arch/arm/include/asm/barrier.h#L23

#define CSDB    ".inst  0xe320f014"

为Spectre添加了一条新指令,内核决定暂时对其进行硬编码。


0
投票

.byte是一个指令,允许您声明一个只有通过检查才能知道的常量字节而没有任何上下文。

从GNU汇编程序指南:

.byte  74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
© www.soinside.com 2019 - 2024. All rights reserved.