我使用 NASM 组装了以下代码:
global _start
section .data
var1 DD 0xA1A2A3A4 ; 4 bytes
var2 DD 0xB1B2B3B4 ; 4 bytes
section .bss
var3: RESD 1 ; 4 bytes
section .text
_start:
mov DWORD [var3], 0xC1C2C3C4
我在 OllyDbg 中打开文件并使其执行指令:mov DWORD [var3], 0xC1C2C3C4
.
这是执行该指令后 OllyDbg 左下 Pane 的状态以及内存映射:
如您所见,数据部分从地址 0x00F02000 开始,大小为 0x1000 字节(因此 var3
是数据部分的一部分)。
编辑:
我使用以下命令创建了目标文件:
nasm -f win32 D:\1.asm
为了创建 EXE 文件,我使用 Visual C++ 2010 链接器使用以下命令:
link D:\1.obj /OUT:D:\1.exe /ENTRY:start /SUBSYSTEM:CONSOLE
最佳答案
这是由 Microsoft 链接器执行的优化。
PE 格式规范要求为每个部分分配 VirtualSize 字节。 VirtualSize 通常为 4 KB,是 Windows 上文件对齐倍数和内存页的大小。由于您的 .data
部分小于 4 KB,因此之后可以轻松容纳未初始化的数据,从而占据“闲置”空间。
如果要引入单独的 .bss
部分,那么这将使二进制文件变得更大并增加加载时间,而没有任何令人信服的原因。链接器选择将 .data
和 .bss
部分合并为一个。
这些附加数据(否则会进入 .bss
部分)不会增加 .data
部分的原始大小因为这些数据实际上不需要存储在二进制文件中的任何位置。因此,它与.bss
本质上具有相同的效果。
如Paweł Łukasik observed ,MinGW 的链接器不执行相同的优化。
Borland 的 TLINK(现在可能仅具有历史意义)从未发出 .bss
部分。它总是扩展 .data
部分的虚拟大小。
关于assembly - NASM 中的 .bss 部分中声明的变量是否会加载到进程的数据部分而不是进程的 bss 部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45029393/