标签和 dd 声明在 NASM 中如何工作? C相当于什么?

How do labels and dd declarations work in NASM? What's the C equivalent?

我正在尝试理解 C 中某些 nasm 习语的等价物,例如这些习语:

%define CONSTANT1 1
%define CONSTANT2 2

1) section name_section data align=N
    v1: dd 1.2345678
    v2: dd 0x12345678
    v3: dd 32767
    v4:
    v5: dd 1.0
    v6:
        dd 1.0, 2.0, 3.0, 4.0,
        dd 5.0, 6.0, 7.0, 8.0

2) section name_section bss align=N
    v7:
        resd 1

3) global _function_name@0
    section name_section code align=N
    _function_name@0:
        ...

4) global _g_structure1
    global _g_structure2
    section name_section data align=N
    _g_structure1:
        dw 01h
        dw 2
    _g_structure2:
        dd CONSTANT1
        dd CONSTANT2

5) section section_name code align=N
    function_name:
        ...

nasm 文档 here and here 没有阐明太多。猜猜我的问题是:

dd 存储由参数给出的 DWORDS 序列。所以 dd 1 将在当前位置存储 4 字节值 0x00000001(因为它针对的是小端架构,所以你最终会得到字节 0x01 0x00 0x00 0x00)。

节通常不会直接在 C 中公开 - 它更多是由编译器、链接器和 运行时间加载器处理的较低级别的问题。因此,一般来说 您的工具链会处理将代码和数据正确分配到各个部分中的问题。例如,编译器会将实际汇编的代码放入.text段,将静态初始化的数据放入.data段,最后将未初始化或零初始化的静态分配数据放入.bss ] 节等。细节并不是 C 本身的一部分,并且会因平台和可执行文件格式而异(例如,并非所有平台都具有相同类型的部分)。

另一方面,在使用汇编时,您需要更加了解节。例如,如果您有可变数据,重要的是它结束于与您的代码不同的部分,因为您不想 运行 进入只读 .text 部分,或自我修改-代码误报等

部分对齐是 运行 时间加载器的一个指令,它告诉它该部分所需的最小对齐方式。您可以使用一些编译器或特定于平台的选项在您的 C 代码中影响它 - 例如如果您请求静态分配的数组具有 32 位对齐,则 .data 部分可能会提升为至少 32 字节对齐。 C 没有标准的方法来实际请求这种对齐,但是您可以使用特定于平台的扩展,例如 posix_memalign, gcc's aligned attribute, or even #pragma pack. C++11 on the other hand has alignas 以标准方式执行此操作。

@N 后缀是 stdcall name mangling.

的结果

您可以借助 nasm 中的 GLOBAL 指令声明全局标签。正如 Peter 指出的那样,这只会修改随后声明的标签的属性,而实际上并没有声明标签本身(仍然以通常的方式完成)。该指令还有其他 format-specific options ,例如,它允许您将导出的符号声明为函数。

NASM global label 指令实际上并未声明 [​​=11=]。它只是修改当你声明它时它将拥有的范围, label:.

它与 C 相反,其中全局是默认值,您必须使用 static 来获取此编译单元私有的非导出符号。


v4: is empty, what does that mean?

将标签视为零宽度指针。标签本身没有大小,它只是标记二进制文件中的那个位置。 (并且您可以在同一位置放置多个标签)。

NASM 没有类型,所以它与 void*.

非常相似