FLAT操作数对SEGMENT指令的影响?

Lyc*_*can 5 x86 assembly masm

MASM提供SEGMENT指令.该指令采用了几个参数.该use参数可以取值FLAT.我不清楚这个价值是做什么的.

微软的文档指定其为一个公认的价值,但没有试图来形容它:

使用
USE16,USE32,FLAT

在线提供的汇编语言程序设计一书提到它,但称其超出范围并建议阅读MASM程序员指南:

use32flat操作数告诉MASM以产生用于一个32位段代码.由于本文不涉及保护模式编程,因此我们不会考虑这些选项.有关更多详细信息,请参阅MASM程序员指南.

在Microsoft的MASM 6.1程序员指南中,在描述该SEGMENT指令的部分中,FLAT提到了该值,但从未描述过它的影响:

size属性可以是USE16,USE32FLAT.

FLAT操作数对SEGMENT指令有什么影响?

Ros*_*dge 5

对于大多数用途,在段指令中使用FLAT关键字与USE32具有相同的含义.USE32和FLAT关键字都表明该段可以大于64K,并且在段中组装的任何指令都应该使用32位编码而不是16位编码.区别在于汇编程序对CS寄存器的假设.通常,SEGMENT指令会产生一个隐式ASSUME CS:xxx指令,其中xxx是段的名称,但是使用FLAT会导致隐式指令ASSUME CS:FLAT.

ASSUME指令告诉汇编器将哪些段加载到哪个段寄存器中,以便它可以在需要时自动使用正确的段覆盖.在大多数32位操作系统使用的平板存储器模型中,只有一个4 GB的段.告诉汇编程序可以通过该段寄存器访问程序中定义的所有段,告诉汇编程序它可以采用段寄存器.例如ASSUME DS:FLAT,所有段都可以通过DS寄存器访问.另一方面ASSUME DS:_DATA,DS寄存器只能用于访问_DATA段而不能用于访问任何其他段.

您可以通过汇总以下代码来查看此行为:

_DATA   SEGMENT PUBLIC USE32
var DD  ?
_DATA   ENDS

_TEXT   SEGMENT PUBLIC PARA 'CODE' FLAT

    mov eax, [zero]
    mov [var],eax 

    ASSUME  DS:FLAT

    mov eax, [zero]
    mov [var],eax 

    ASSUME  CS:_TEXT  
    ASSUME  DS:_DATA

    mov eax, [zero]
    mov [var],eax 

zero    DD  0

_TEXT   ENDS

    END
Run Code Online (Sandbox Code Playgroud)

如果您反汇编生成的目标文件,您会看到前两条指令:

  00000000: 2E A1 00 00 00 00  mov         eax,dword ptr cs:[zero]
  00000006: 2E A3 00 00 00 00  mov         dword ptr cs:[var],eax
Run Code Online (Sandbox Code Playgroud)

对于这两条指令,汇编程序必须使用CS段override(2E)才能访问zerovar.这是因为虽然汇编程序知道CS可用于访问所有段,包括_TEXT_DATA,但它不知道可以使用任何其他段寄存器来访问这些semgents.

这是在指令之后为接下来的两条指令生成的代码ASSUME DS:_FLAT:

  0000000C: A1 00 00 00 00     mov         eax,dword ptr [zero]
  00000011: A3 00 00 00 00     mov         dword ptr [var],eax
Run Code Online (Sandbox Code Playgroud)

现在汇编程序知道CS和DS都可以用来访问所有段.由于使用DS访问zero并且var不需要段覆盖,因此它使用DS而不是CS,从而导致更短的指令.

最后,在ASSUME DS:_DATAASSUME CS:_TEXT指令之后的最后两条指令显示如果根本不使用FLAT关键字,代码汇编器将生成:

  00000016: 2E A1 00 00 00 00  mov         eax,dword ptr cs:[zero]
  0000001C: A3 00 00 00 00     mov         dword ptr [var],eax
Run Code Online (Sandbox Code Playgroud)

在这种情况下,汇编程序假定CS只能用于访问_TEXT,而DS只能用于访问_DATA.它必须使用CS覆盖来访问zero,而它只能var通过DS 访问,这不需要段覆盖.

请注意,如果您在上面的示例代码中将SATMENT指令中的FLAT更改为USE32,则第一条指令最终使用CS覆盖,但第二条指令会生成以下错误:

error A2074:cannot access label through segment registers
Run Code Online (Sandbox Code Playgroud)

那是因为虽然汇编程序知道它可以通过CS寄存器访问_TEXT,但它不知道它可以用来访问_DATA的任何段寄存器.

如果您.MODEL FLAT在代码开头使用该指令,则不必担心任何此类指令.然后USE32和FLAT在段指令中具有完全相同的效果,因为假定每个段寄存器都是FLAT.