标签和 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
和类似内容?
- 您似乎可以声明 N 个类型为 X 字节对齐的 {code, bss, data} 部分,这在 C 中是什么意思?
- 有@N后缀的函数,那是什么意思?
- global...您声明全局标签?在什么范围内? nasm 个文件?
- v4: 为空,什么意思?
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*
.
非常相似
我正在尝试理解 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
和类似内容? - 您似乎可以声明 N 个类型为 X 字节对齐的 {code, bss, data} 部分,这在 C 中是什么意思?
- 有@N后缀的函数,那是什么意思?
- global...您声明全局标签?在什么范围内? nasm 个文件?
- v4: 为空,什么意思?
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*
.