Hi,
debug build does not work
mywindow2useBug.asm(9) : Warning A4299: BSS data in BIN output could have side effects
mywindow2useBug.asm(9) : Warning A4299: BSS data in BIN output could have side effects
mywindow2useBug.asm : Error A2197: Unknown fixup type: 10 at .debug$S.37
mywindow2useBug.asm : Error A2197: Unknown fixup type: 10 at .debug$S.55
mywindow2useBug.asm : Error A2197: Unknown fixup type: 10 at .debug$S.124Some in-depth information (
question and answer is completely copied) -
Effects of the FLAT operand to the SEGMENT directive? https://stackoverflow.com/questions/45124341/effects-of-the-flat-operand-to-the-segment-directiveMASM provides a SEGMENT directive. The directive takes several parameters. The use parameter can take a value FLAT. It's unclear to me what this value does.
The Microsoft docs
https://docs.microsoft.com/en-us/cpp/assembler/masm/segment specify it as an accepted value but make no attempt to describe it:
use
USE16, USE32, FLATThe book The Art of Assembly Language Programming available online mentions it but calls it out of scope and recommends reading the MASM Programmer's Guide:
The use32 and flat operands tell MASM to generate code for a 32 bit segment. Since this text does not deal with protected mode programming we will not consider these options. See the MASM Programmer's Guide for more details. In the MASM 6.1 Programmer's Guide from Microsoft, in the section describing the SEGMENT directive, the FLAT value is mentioned but its effects are never described:
The size attribute can be USE16, USE32, or FLAT.What are the effects of the FLAT operand to the SEGMENT directive?Answer:
For most purposes the FLAT keyword when used in a segment directive has the same meaning as USE32. Both the USE32 and FLAT keywords indicate that the segment can be bigger than 64K and that any instructions assembled in the segment should use 32-bit encoding rather than 16-bit encoding. The difference is what the assembler assumes about the CS register. Normally a SEGMENT directive results in an implicit ASSUME CS:xxx directive where xxx is the name of the segment, but with FLAT it results in an implicit ASSUME CS:FLAT.
The ASSUME directive tells the assembler which segments are loaded into which segment registers so it can automatically use the correct segment overrides where needed. In the flat memory model used by most 32-bit operating systems there only one single 4 gigabyte segment. Telling the assembler that it can assume a segment register is FLAT tells the assembler that all segments defined in the program can be accessed through that segment register. For example ASSUME DS:FLAT says that all segments can accessed through the DS register. On the other hand ASSUME DS:_DATA says that the DS register can only be used to access the _DATA segment and not any other segment.
You can see this behaviour by assembling the following code:
_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
ENDIf you disassemble the resulting object file you see this for the first two instructions:
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],eaxFor these two instructions the assembler has to use the CS segment override (2E) in order to access zero and var. That's because while the assembler knows that CS can be used to access all segments, including _TEXT and _DATA, it doesn't know that any other segment register can be used to access these semgents.
Here's the code it generates for the next two instructions, after the ASSUME DS:_FLAT directive:
0000000C: A1 00 00 00 00 mov eax,dword ptr [zero]
00000011: A3 00 00 00 00 mov dword ptr [var],eaxNow the assembler knows that both CS and DS can be used to access all segments. Since using DS to access zero and var doesn't require a segment override, it uses DS instead of CS resulting in shorter instructions.
Finally the last two instructions, after the ASSUME DS:_DATA and ASSUME CS:_TEXT directives, show the code assembler would generate if the FLAT keyword isn't used at all:
00000016: 2E A1 00 00 00 00 mov eax,dword ptr cs:[zero]
0000001C: A3 00 00 00 00 mov dword ptr [var],eaxIn this case the assembler assumes CS can only be used to access _TEXT, and DS only to access _DATA. It has to use a CS override to access zero, while it can only access var through DS, which requires no segment override.
Note if you change the FLAT to USE32 in the SEGMENT directive in the example code above then first instruction ends up using a CS override, but the second instruction generates the following error:
error A2074:cannot access label through segment registersThat's because while the assembler knows it can access _TEXT through the CS register, it doesn't know of any segment register it can use to access _DATA.
If you use the .MODEL FLAT directive at the start of you code you shouldn't have to worry about any of this. Then USE32 and FLAT have exactly same effect in segment directives as every segment register is assumed to be FLAT.