对于 code segment 的访问,都知道是使用 CS selector register 。对于 data segment 的访问,则是根据指令或内存的寻址方式来决定使用哪个 selector registers。
1、对于串操作指令来说,在缺省的情况下:源串引用 DS 作为参考对象,目标串引用 ES 作为参考对象。
loadsd /* 从源串 ds:[esi] 中 load 到 eax 中 */
stosd /* 从 eax 中 store 到目标串 es:[edi] 中 */
movsd /* 从源串 ds:[esi] 复制到目标串 es:[edi] 中 */
----------------------------------------------------------------
stosd 缺省使用 ES selector register 来引用数据,而 movsd 更是同时使用了 DS 和 ES selector register 来引用数据。
2、强制性改变缺省的参考对象。
loadsd dword ptr fs:[esi] /* 这里强制性地将缺省引用对象 ES 改变为 FS,这将使用 FS 作为参考对象 */
mov eax, dword ptr es:[eax] /* 强制使用 ES 作为 参考对象 */
-------------------------------------------------------------
以上是使用修改指令前缀方法,强制使用指令的 selector registers 作为引用对象进行数据访问。对于 mov eax, dword ptr es:[eax] 这条指令来说:它的内存操作数 [eax] 缺省是使用 DS 来访问 data segment 的。es:[eax] 则改为使用 ES 来访问 data segment。
将 DS 强制改为 ES 后,当然是使用 ES selector 来读取 data segment descriptor。若 ES = DS 则与缺省情况并无两样,若 ES <> DS 则 ES selector 要先通过权限检查,加载到 ES register 再作访问。
3、push / pop 指令使用 SS 作为参考对象。
push / pop 之类的指令是固定使用 SS selector register 作为引用对象的。push 指令使用 SS 作为目标操作数的引用对象。而 pop 指令使用 SS 作为源操作数的引用对象,这两个是无法改变的。
push 指令的源操作数和 pop 指令的目标操作数,它们的引用对象则是可改的。
4、 基于 ebp 和 esp 的寻址方式使用 SS 作为参考对象
mov eax, dword ptr [ebp+0x0c]
-------------------------------------------
ebp 作为 stack frame base pointer 它缺省是使用 SS 来访问数据的。
实际上等于显式的: mov eax, dword ptr ss:[ebp+0x0c],当然这个情况下,可以强制改为 DS,如:mov eax, dword ptr ds:[ebp+0x0c],这样改为使用 DS 访问数据。
又如:
mov eax, dword ptr [esp]
------------------------------------------------
esp 作为 stack pointer 它缺省是使用 SS 来访问数据的。
实际上等于显式的: mov eax, dword ptr ss:[esp],同样也可以强制改为:mov eax dword ptr ds:[esp] 这样就使用 DS 来访问数据。
5、除了上述几种情况下,其它都是使用 DS 作为缺省的参考对象
大多数情况下,指令的内存操作数都是使用 DS 作为缺省对象来访问数据。
典型的如:
mov eax, [eax]
mov eax, [ebx]
mov byte ptr [esi], 0x0c
等等... ...
6、 在 64 bit 模式下的 selector registers 使用
在 64 bit 模式下 DS、ES、SS 是无效的,因此,已经没有该使用哪个 selector register 来访问数据这种考虑了。所有的 data segment 的 base 都是 0。
无论是:
mov rax, qword ptr [rsp]
mov rax, qword ptr [rbp]
还是:
movsq
mov rax, qword ptr [rax]
--------------------------------------------------
它们的结果都是在基于 0 的 data segment 上进行数据访问。都是在一个平垣的内存块上进行操作。所以,无所谓 selector 是什么?segment register 的值是什么?data segment descriptor 是什么?
但是,FS 和 GS 还是有效的。程序中依旧可以使用 FS 和 GS 访问附加的 data segment。这些附加的 data segment 的 base 值可以不为 0,也就是 FS 和 GS 依旧可以构造有限的 segmentation 功能。
阅读(1398) | 评论(0) | 转发(0) |