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

发布于 2024-12-03 06:32:08 字数 196 浏览 1 评论 0原文

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

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

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

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

While going through some C code having inline assembly I came across the .byte (with a Dot at the beginning) directive.

On checking the assembly reference on web I found that it is used to reserve a byte in memory.

But in the code there was no label before the statement. So I was wondering what is use of an unlabeled .byte directive or any other data storage directive for that matter.

For e.g. if i code .byte 0x0a, how can i use it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情未る 2024-12-10 06:32:08

有几种可能性......这里有一些我能立即想到的:

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

    <前><代码> .byte 0x0a
    标签:
    mov(标签 - 1),%eax

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

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

    <前><代码> .byte 0x66
    移动 $12,%eax

    为了让汇编器发出您想要的代码。

There are a few possibilities... here are a couple I can think of off the top of my head:

  1. You could access it relative to a label that comes after the .byte directive. Example:

      .byte 0x0a
    label:
      mov (label - 1), %eax
    
  2. Based on the final linked layout of the program, maybe the .byte directives will get executed as code. Normally you'd have a label in this case too, though...

  3. Some assemblers don't support generating x86 instruction prefixes for operand size, etc. In code written for those assemblers, you'll often see something like:

      .byte 0x66
      mov $12, %eax
    

    To make the assembler emit the code you want to have.

夜司空 2024-12-10 06:32:08

最小可运行示例

.byte 无论您身在何处,都会吐出字节。是否有标签指向字节并不重要。

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

Carl 提到了这一点,但这里有一个完整的示例,可以让它进一步深入:Linux x86_64 的 true 实现,其中抛出了 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 内核上的 Spectre 解决方法,使用类似的 .inst 指令:https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/arch/arm/include/asm/barrier.h#L23

#define CSDB    ".inst  0xe320f014"

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

Minimal runnable example

.byte spits out bytes wherever you are. Whether there is a label or not pointing to the byte, does not matter.

If you happen to be in the text segment, then that byte might get run like code.

Carl mentioned it, but here is a complete example to let it sink in further: a Linux x86_64 implementation of true with a nop thrown in:

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

produces the exact same executable as:

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

since nop is encoded as the byte 0x90.

One use case: new instructions

One use case is when new instructions are added to a CPU ISA, but only very edge versions of the assembler would support it.

So project maintainers may choose to inline the bytes directly to make it compilable on older assemblers.

See for example this Spectre workaround on the Linux kernel with the analogous .inst directive: https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/arch/arm/include/asm/barrier.h#L23

#define CSDB    ".inst  0xe320f014"

A new instruction was added for Spectre, and the kernel decided to hardcode it for the time being.

天荒地未老 2024-12-10 06:32:08

下面是一个内联汇编的示例:(

#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;
}

参见 编译器 asm 输出以及 Godbolt 编译器资源管理器上最终二进制文件的反汇编。)

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

Here's an example with inline assembly:

#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;
}

(See compiler asm output and also disassembly of the final binary on the Godbolt compiler explorer.)

You can replace .byte 0xb8, 0x01, 0x00, 0x00, 0x00 with mov $1, %%eax
the run result will be the same. This indicated that it can be a byte which can represent some instruction eg- move or others.

只是我以为 2024-12-10 06:32:08

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

来自 GNU 汇编器指南:

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

The .byte is a directive that allows you to declare a constant byte only known through inspection without any context.

From the GNU Assembler Guide:

.byte  74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文