在本汇编指令中
mov ax, es:[bx]
:是什么意思
:
4dc9hkyq1#
具体是什么:做什么?“:“不“做”任何事情,就像大多数高级编程语言中的“.”不“做”任何事情一样。":“与<segment register> : <address expression>形式的指令一起使用。默认情况下,所有x86指令都有一个“默认段选择器”,用于确定指令的“内存操作数”所指示的地址。这通常是“ds”或“ss”,这取决于指令。然而,通过在指令二进制编码中指定适当的“指令前缀字节”,指令可以指定CS、DS、ES、SS、FS和GS段寄存器中的任何一个。在16位“真实的模式”程序中,段寄存器中的值用于确定存储器地址的“高阶位”。它与指令中指定的内存地址相结合,以生成指令引用的实际地址。这允许在16位硬件上运行的程序访问大于16位的内存空间,前提是它们可以将内存分组为4k块,这些块可以相对于“段选择器”寄存器进行访问。在32位程序中,段选择器实际上是一个结构的索引,它描述了一个动态Map,包括偏移量和大小。通过将索引结构中存在的信息与指令中存在的存储器操作数组合来计算地址。大多数时候,在32位程序中,大多数段寄存器指向指定整个32位地址空间的结构。主要的例外是“fs”寄存器,它指定Map到操作系统定义的特殊数据结构的偏移量和大小。它被用作内核空间和用户空间之间的通信机制之一。它通常包含对当前“进程或线程”的内核表示的所有“用户空间可见”属性的访问。64位程序完全避开段寄存器。除了FS和GS之外的所有段寄存器都被定义为无效,并且表现得好像它们Map了整个用户空间。FS寄存器通常用于提供对正在执行的程序的当前“32位上下文”的访问。“GS”寄存器通常用于提供对当前“64位上下文”的访问。这允许32位程序在64位系统上运行,但也允许64位内核(以及32位进程和64位进程之间的Map层)访问它需要工作的64位上下文。回答你最初的问题很可能(在不了解处理器或操作系统模式的情况下),指令:
<segment register> : <address expression>
实际上相当于:
mov ax, [bx]
然而,它使用16位寄存器的事实表明它可能是一个真实的模式程序,在这种情况下,它可能意味着:
mov ax, [<addr>]
其中addr ==(es << 4)+ [bx]
wqsoz72f2#
:是表示地址的段部分的惯例。因此,ES是一个段(因此,例如在这个位置上的SI将是无效的),而[BX]是该段内的偏移量;用作偏移量的段寄存器将同样无效并产生错误。
ES
SI
[BX]
zbwhf8kr3#
当您访问进程内存中的某些数据时,总会涉及到一个段寄存器,它定义了一个内存窗口,并将主寄存器作为偏移量。这些寄存器为cs、ds、es、ss、fs和gs。其中一些段寄存器有特殊用途,如cs(代码段)或ss(堆栈段)。当你用一个寄存器访问数据时,就像你的例子一样,那么一个默认的段被汇编程序选择。此段寄存器编码在指令中。在某些情况下,您希望覆盖默认选择,并使用与默认寄存器不同的段寄存器,您可以通过使用段覆盖来实现这一点,这就是您的示例正在做的事情。当执行
cs
ds
es
ss
fs
gs
mov eax, [ebx]
默认情况下,将使用ds段但是带段覆盖的指令
mov eax, es:[ebx]
指定应该使用es段。在Windows中,默认情况下,ds和es指向相同的段,因此不需要此重写,因为它将访问相同的线性和物理地址。
pcww981p4#
DS:OFFSET其中DS是段地址,OFFSET是相对于段的偏移。这意味着像这样计算地址:DS * size_of_segment + OFFSET通常,对于x86,段的大小是16字节。举例来说:
DS: 07C0H 0000 0111 1100 0000 + OFFSET: 0000H 0000 0000 0000 0000 = 07C00H 0000 0111 1100 0000 0000
4条答案
按热度按时间4dc9hkyq1#
具体是什么:做什么?
“:“不“做”任何事情,就像大多数高级编程语言中的“.”不“做”任何事情一样。":“与
<segment register> : <address expression>
形式的指令一起使用。默认情况下,所有x86指令都有一个“默认段选择器”,用于确定指令的“内存操作数”所指示的地址。这通常是“ds”或“ss”,这取决于指令。然而,通过在指令二进制编码中指定适当的“指令前缀字节”,指令可以指定CS、DS、ES、SS、FS和GS段寄存器中的任何一个。在16位“真实的模式”程序中,段寄存器中的值用于确定存储器地址的“高阶位”。它与指令中指定的内存地址相结合,以生成指令引用的实际地址。这允许在16位硬件上运行的程序访问大于16位的内存空间,前提是它们可以将内存分组为4k块,这些块可以相对于“段选择器”寄存器进行访问。
在32位程序中,段选择器实际上是一个结构的索引,它描述了一个动态Map,包括偏移量和大小。通过将索引结构中存在的信息与指令中存在的存储器操作数组合来计算地址。
大多数时候,在32位程序中,大多数段寄存器指向指定整个32位地址空间的结构。主要的例外是“fs”寄存器,它指定Map到操作系统定义的特殊数据结构的偏移量和大小。它被用作内核空间和用户空间之间的通信机制之一。它通常包含对当前“进程或线程”的内核表示的所有“用户空间可见”属性的访问。
64位程序完全避开段寄存器。除了FS和GS之外的所有段寄存器都被定义为无效,并且表现得好像它们Map了整个用户空间。FS寄存器通常用于提供对正在执行的程序的当前“32位上下文”的访问。“GS”寄存器通常用于提供对当前“64位上下文”的访问。这允许32位程序在64位系统上运行,但也允许64位内核(以及32位进程和64位进程之间的Map层)访问它需要工作的64位上下文。
回答你最初的问题
很可能(在不了解处理器或操作系统模式的情况下),指令:
实际上相当于:
然而,它使用16位寄存器的事实表明它可能是一个真实的模式程序,在这种情况下,它可能意味着:
其中addr ==(es << 4)+ [bx]
wqsoz72f2#
:
是表示地址的段部分的惯例。因此,ES
是一个段(因此,例如在这个位置上的SI
将是无效的),而[BX]
是该段内的偏移量;用作偏移量的段寄存器将同样无效并产生错误。zbwhf8kr3#
当您访问进程内存中的某些数据时,总会涉及到一个段寄存器,它定义了一个内存窗口,并将主寄存器作为偏移量。这些寄存器为
cs
、ds
、es
、ss
、fs
和gs
。其中一些段寄存器有特殊用途,如cs
(代码段)或ss
(堆栈段)。当你用一个寄存器访问数据时,就像你的例子一样,那么一个默认的段被汇编程序选择。此段寄存器编码在指令中。在某些情况下,您希望覆盖默认选择,并使用与默认寄存器不同的段寄存器,您可以通过使用段覆盖来实现这一点,这就是您的示例正在做的事情。当执行
默认情况下,将使用
ds
段但是带段覆盖的指令
指定应该使用
es
段。在Windows中,默认情况下,ds
和es
指向相同的段,因此不需要此重写,因为它将访问相同的线性和物理地址。pcww981p4#
DS:OFFSET其中DS是段地址,OFFSET是相对于段的偏移。
这意味着像这样计算地址:DS * size_of_segment + OFFSET
通常,对于x86,段的大小是16字节。
举例来说: