为什么偏移运算符 return 是一个巨大的偏移量,而变量位于 .data 段的开头?

Why does the offset operator return a huge offset, whereas a variable is located at the beginning of .data segment?

如果偏移运算符应该 return 变量与其封闭段开头的距离,那么为什么 returned 偏移总是一些巨大的数字?在以下示例中,变量 num 位于 .data 段中的第一个。它不是必须在 0 偏移处吗?在我的机器上,我得到 00007FF7C90A4000 偏移量。没看懂。

.data 
num byte 123
.code   
mov rsi, offset num

这看起来像是 64 位代码。 64 位代码通常在 64 位保护模式 OS 下运行,例如 Windows 或 Linux。那些系统在任意起始地址加载程序,不一定是逻辑0。所以你得到的偏移量是数据段中变量的偏移量,加上数据段的起始地址在进程内存中。前者可能为零,但后者可以是任何值。

请注意,您的程序看到的偏移量是虚拟地址,而不是物理地址。它确实对应于一些实际内存,但底层物理地址只有 OS 内核知道。

事实上,操作系统会将您的文件加载到一个随机的、不可预测的起始地址,以阻止某些 class 的黑客攻击(利用)。

OFFSET 运算符 return 从段开始处的偏移量,但是 64 位(和 32 位)代码使用平面内存模型,其中只有一个段并且该段覆盖整个从地址 0 开始的线性地址 space。.data.code 指令实际上并不创建两个不同的段,它们在一个平面段中创建两个部分。

您的特定情况下偏移量如此之高的原因是 Windows 如果可以的话,将在随机线性地址加载程序。这是一种安全措施,可以使各种缓冲区溢出攻击更难发挥作用。由于单个平面段的基数为 0,并且 Windows 显然决定将程序加载到 0x00007FF7C90A0000 左右的地址,因此 .data 部分开头的偏移量最终与地址 0 处的段开始。