该指令正在从内存加载新的 EIP 值ds:[40207A]
。即地址处有一个函数指针40207A
。 (它推送一个返回地址,因为这是一个call
不只是一个jmp
.)
The ds:
意味着指令引用数据段中的内存 - 在现代操作系统上几乎可以忽略,因为它们使用平面地址空间模型运行(代码、数据和堆栈段都引用相同的内存范围,并且处理内存保护与分页)。
The ds:
是为了向您展示它绝对是一个内存操作数,并提醒您它使用哪个段/显示没有段覆盖前缀(可能除了ds
前缀,因为这已经是默认值)。
EDIT:
稍微详细说明一下 - 请注意,为了简单起见,这是在运行 Windows 的 32 位保护模式的上下文中进行的。
A 段寄存器(CS,DS,SS,ES,FS,GS) 持有selector
指向一个descriptor
。有两个描述符表:全局(GDT)和本地(LDT),并且选择器有一个位指示要使用哪个。 Windows(几乎?)专门使用全局表。
A 描述符 is 基本上 a {起始地址,大小}对 - 还有更多内容,但这超出了本文的范围。
Windows 使用一个扁平内存模型:每个进程有一个从内存地址0开始的4GB地址空间,并使用paging将进程彼此隔离。
由于进程具有这种扁平的世界观,因此它们使用 {0, 4GB} 描述符与所有段一起运行 - 因此,Windows 可以仅使用一些全局描述符,并让所有进程都使用这些描述符,而不是分配每个进程描述符。
EDIT 2:
The 便携式可执行文件格式定义sections
,与 x86 无关segments
- 即使存在一些概念重叠。 PE EXE 几乎可以具有您希望的任何部分布局,但正常情况是分为(至少)代码(读/执行)、数据(读/写)、资源(只读?)。将可执行文件分割成多个部分可以将 x86 页级内存保护应用于内存范围。
EDIT 3:
虽然普通段不会随进程而改变,但 Windows 使用FS
寄存器指向每thread TIB结构。
EDIT 4:
See this以获得概述。这是来自 80386 的旧文档,但该信息仍然适用。