.byte 汇编指令在 gnu 汇编中有啥用?

Posted

技术标签:

【中文标题】.byte 汇编指令在 gnu 汇编中有啥用?【英文标题】:What is the use of .byte assembler directive in gnu assembly?.byte 汇编指令在 gnu 汇编中有什么用? 【发布时间】:2011-11-09 13:23:50 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

最小可运行示例

.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 添加新指令,但只有非常先进的汇编程序版本会支持它。

因此项目维护者可以选择直接内联字节以使其可在较旧的汇编器上编译。

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

#define CSDB    ".inst  0xe320f014"

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

【讨论】:

【参考方案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 运行结果将是相同的。这表明它可以是一个字节,可以表示一些指令,例如移动或其他。

【讨论】:

【参考方案3】:

有几种可能性...这里有几个我能想到的:

    您可以相对于.byte 指令之后 的标签来访问它。示例:

      .byte 0x0a
    label:
      mov (label - 1), %eax
    

    根据程序的最终链接布局,.byte 指令可能会作为代码执行。通常在这种情况下你也会有一个标签,不过......

    一些汇编程序不支持为操作数大小等生成 x86 指令前缀。在为这些汇编程序编写的代码中,您经常会看到类似以下内容:

      .byte 0x66
      mov $12, %eax
    

    让汇编器发出你想要的代码。

【讨论】:

3) 中的那个汇编器急需一个补丁:-) .byted* pseudo-ops有什么区别? 我希望它们是一样的。 .byte 0x66mov $12, %eax 的长度变化,因此您的示例将在 32 位模式下解码为 mov $12, %ax / add %al,(%rax)(%eax)。第二条指令是 mov eax, imm16 不消耗的 32 位立即数的剩余 00 00 字节。这对硬件来说也很棘手,并且会导致 Intel CPU 上的 LCP 预解码停止(LCP = 长度变化前缀)。【参考方案4】:

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

来自 GNU 汇编器指南:

.byte  74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.

【讨论】:

以上是关于.byte 汇编指令在 gnu 汇编中有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

请问懂汇编的人:rsp寄存器有啥用

汇编 里的near 和far有啥用啊?

GNU ARM 汇编指令

博文连载ARM编译器ARM汇编与ARM GNU汇编

GNU ARM汇编快速入门

GNU ARM 汇编基础笔记