The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: 2B||!2B on June 03, 2019, 02:41:19 PM

Title: USE directive error
Post by: 2B||!2B on June 03, 2019, 02:41:19 PM
Hi,

I read the PDF of UASM but i cannot get the USE directive to work.

USE64


xor ax,ax
xor eax,eax
xor rax,rax

: Error A2169: General Failure

What is the error?
Title: Re: USE directive error
Post by: 2B||!2B on June 04, 2019, 10:07:08 AM
I found a fix for this problem.
In case anyone is facing the same issue, here is how to fix it.

add these on top of the project

option flat:1
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE


However, there are still some issues that need to be resolved.

: Warning A4299: BSS data in BIN output could have side effects

Using USE, this will cause the compiled project to have 2 code sections.
.text
_flat


That will cause problems with all .data writing at runtime since the _flat section is not writeable and now it has replaced the .data section.
I am waiting for some clarification from the coder. Maybe i am doing something wrong here.
Title: Re: USE directive error
Post by: aw27 on June 04, 2019, 06:02:21 PM
I would suggest you to produce a complete example, including showing how you are trying to build it.
Odds are you doing things wrong, so this will save people time as well as tear and wear of the brain cells
Some people can't even read properly the manual before asking questions, this may or not be your case - I believe it is your case because the sample provided in the manual builds successfully.

Title: Re: USE directive error
Post by: 2B||!2B on June 05, 2019, 05:03:41 AM
Hi AW,

Thanks for the tip.
Is just copied and pasted from the manual to an empty project, thats why i did not post project files.
I also managed to fix that by posting later on.
The new issue is different and is the aftermath.
I will post the files in here.
Title: Re: USE directive error
Post by: 2B||!2B on June 05, 2019, 10:14:34 AM
I attached a sample that demonstrates the issue.

The Val variable is set to be in .data? section. However, when compiling, .data section is been merged into _flat section which has no writeable flag and thus causing access violation exception.

Access violation when writing to [00401000]


Title: Re: USE directive error
Post by: jj2007 on June 05, 2019, 11:45:04 AM
That is indeed weird. Here is the essential code:
.486
.model flat,stdcall
option casemap:none
option flat:1
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

.data?
Val dd ?

.code
start:
     use64
        POP rax
        MOV RCX, RAX

     use32
      MOV EAX,1
      MOV Val,EAX
        RET
end start


As seen from Olly:
00401000       .  00000000                    dd 00000000
<ModuleEntryP Ú$  58                          pop eax
00401005      ³.  48                          dec eax
00401006      ³.  8BC8                        mov ecx, eax
00401008      ³.  B8 01000000                 mov eax, 1
0040100D      ³.  A3 00104000                 mov [401000], eax
00401012      À.  C3                          retn


The mov [401000], eax causes the exception :sad:

Another interesting question, though, is how the cpu knows that instead of the pop eax it must perform a pop rax :rolleyes:
Title: Re: USE directive error
Post by: aw27 on June 05, 2019, 01:11:11 PM
Weird is that half of the chapter explains the scope for the clauses and even hints how to build things. Regardless of that, people still apply the same old receipt of one size fits all.
Title: Re: USE directive error
Post by: LiaoMi on June 05, 2019, 06:00:43 PM
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.124



Some 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-directive (https://stackoverflow.com/questions/45124341/effects-of-the-flat-operand-to-the-segment-directive)

MASM 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 (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, FLAT


The 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

    END

If 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],eax

For 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],eax

Now 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],eax

In 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 registers

That'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.
Title: Re: USE directive error
Post by: LiaoMi on June 05, 2019, 08:10:35 PM
workaround once downloaded in one of the topics on the forum :thumbsup:

.386
.model flat

includelib msvcrt.lib
exit proto C :dword
_getch proto C
printf proto C :dword, :vararg

call_as_x64 macro lbl
    db 9ah         ;call 0x33:OFFSET x64-proc
    dd OFFSET lbl
    dw 33h
endm

.x64
x64 SEGMENT EXECUTE USE64

; let's do some 64 bit arithmetic
mov eax,DWORD ptr [rsp+8]
mov r10,QWORD ptr [rax]
shr r10,16
mov QWORD ptr [rax],r10

retf

x64 ENDS

.data
fmt1 db "%p%p",13,10

.code
main proc
;LOCAL sysi:SYSTEM_INFO
LOCAL myQW:QWORD
mov DWORD ptr myQW[0],0AAAAAAAAh
mov DWORD ptr myQW[4],0BBBBBBBBh
invoke printf, addr fmt1, dword ptr myQW[4], dword ptr myQW[0]
lea eax,myQW
push eax
call_as_x64 x64
invoke printf, addr fmt1, dword ptr myQW[4], dword ptr myQW[0]
invoke _getch
invoke exit,0
main endp
end main
Title: Re: USE directive error
Post by: LiaoMi on June 05, 2019, 08:46:28 PM
 :thumbsup:

.586
.MODEL FLAT, C
.STACK
.DATA
KeyKey dd 10000000h
.CODE             ;Indicates the start of a code segment.

mainCRTStartup PROC; run_asm64
db 0EAh    ; jump to enter 64 bit
dd offset LocEnter
db 033h, 000h
LocEnter:
; Add the 64bit opcodes within the two lines
; warning: remember to preserve the registers you trash
;-----------------------------------------------------
db 051h, 048h, 0b9h                              ; push rcx / mov rcx, offset Key
dd offset KeyKey
dd 0
db 081h, 001h, 078h, 056h, 034h, 012h, 059h      ; add dword ptr [rcx], 012345678h / pop rcx
;----------------------------------------------------
db 048h, 083h, 0ech,
004h
; sub  rsp,4

db 089h, 004h,
024h 
; mov  dword ptr [rsp], eax (save eax forlater)

db 048h, 08bh,
0c4h 
; mov rax,rsp

db 06ah,02bh   
; push stack segment selector

db 50h   
; push stack pointer (in rax)

db 068h, 046h, 002h, 000h,
000h
; push eflags

db 06ah, 023h   
; push code selector
db 068h
dd offset LocExit   ; push instruction pointer
db 048h, 0cfh    ; iretq
LocExit:
pop eax     ; restore eax
ret

mainCRTStartup ENDP ; run_asm64
END


also does not work ..

.486
.model flat,stdcall
option casemap:none
option flat:1
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

.data?
;zero    DD  0
Val dd ?

.code
start:
new proc
;jmp far ptr 33h:use64Enter
db 0EAh    ; jump to enter 64 bit
dd offset use64Enter
db 033h, 000h
use64Enter:
     use64
        POP rax
        MOV RCX, RAX
push LocExit   ; push instruction pointer
        iretq
LocExit:
     use32
      MOV EAX,1
      MOV Val,EAX
        RET
new endp
end start


From the documentation ...

6. OPTION FLAT

For some types of low-level programming, especially OS kernel and boot-loader code the model
adopted by some other non-MASM style assemblers lends itself very well to mixing code of
different bit types, for example switching between real and protected or long mode.
To make this type of programming more straight-forward UASM implements a flat mode. A single
code section is create with the normal .code simplified directive, however the new directives
USE16/USE32/USE64 can be used on their own to switch the current code-generation mode.
For example:
option flat:1



.code

org 0h
USE16

xor ax,ax
xor eax,eax


org 100h
var1 dd 10

USE32
xor ax,ax
xor eax,eax

org 1000h
var2 dd 20

USE64

xor ax,ax
xor eax,eax
xor rax,rax
Title: Re: USE directive error
Post by: LiaoMi on June 05, 2019, 09:12:40 PM
Another example  :tongue:

mywindow2useBug.asm(10) : Warning A4299: BSS data in BIN output could have side effects
mywindow2useBug.asm(17) : Error A2069: Segment, group or segment register expected
mywindow2useBug.asm: 35 lines, 1 passes, 2 ms, 1 warnings, 1 errors
Microsoft (R) Incremental Linker Version 14.21.27702.2
Copyright (C) Microsoft Corporation.  All rights reserved.


.486
.model flat,stdcall
option casemap:none
option flat:1
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

.data?
Val dd ?

.code
start:
new proc
        XOR ECX, ECX
        CALL 33h:Our64Proc ; <- Error A2069: Segment, group or segment register expected
      MOV EAX,1
      MOV Val,EAX
        RET
new endp

Our64Proc proc  ;This proc is x64 code
     use64
        CALL @F
        DB "This was generated using 64 bit ASM code.", 0
@@:
        POP RAX
        MOV RCX, RAX
     use32
        RETF
Our64Proc endp

end start
Title: Re: USE directive error
Post by: aw27 on June 05, 2019, 09:31:14 PM
It is very clear in the manual (although extremely terse  :sad:) what is the purpose of this. It is also very clear (:joking:) that we were expected to produce BIN output, i.e use a special switch that UASM has, the BIN switch. If all this sounds like a riddle, it is indeed a riddle.  :skrewy:

So I produced an example that everybody can run without having to format floppy disks or other unusual practice. The example, is an extremely small .exe file.

You must test by running the included test.bat, not the mixedCode.exe.

Title: Re: USE directive error
Post by: hutch-- on June 06, 2019, 12:32:49 AM
 :skrewy:

Expected return value is 123456. Returned value is: 123456
Press any key to continue . . .
Title: Re: USE directive error
Post by: johnsa on June 06, 2019, 02:59:02 AM
Hi,

Just to add to what AW has been saying.

The purpose of USE16, USE32, USE64 directives is to work in conjunction with option flat:1

This is a "special" mode not for general use under Windows, Linux etc.

It must be used with -BIN output type.

It will generate a flat binary image without segments (while still allowing simplified directives like .code) that can assemble instructions based on the current state (IE: USE16, USE32, USE64).
If you are familiar with any boot loading, kernel code these constructs become very handy and it replicates a style of coding/usage similar to that available in FASM.

for example, if you wanted to write a a block of code which had some real mode 16bit stuff and some 32bit protected mode stuff, instead of having:


code16 segment para public use16 'code16'
assume cs:code16
.
.
jmp far ptr lbl2
.
.

code32 segment para public use32 'code32'
assume cs:code32

lbl2:


as you might with MASM, and often then you have to hack or hand-code in the far jumps.

instead you can do something like:


USE16

mov ax,13h
int 10h
jmp far ptr lbl2

USE32

; Here we are in protected mode..
lbl2:


Obviously I've left out lots of the code above but you get the idea..I implemented this mode specifically for OS development stuff I was working on.
It also allows correct evaluation of org directives, offsets and addr across different bit-sizes (keeps your life a bit simpler).
Title: Re: USE directive error
Post by: 2B||!2B on June 07, 2019, 02:21:11 PM
Thank you guys for the contribution.
I understand the use now.
My bad, i thought the USE directive can be used with normal PE files like the one in FASM.
Title: Re: USE directive error
Post by: aw27 on June 11, 2019, 04:46:26 PM
This is the list of bugs I have found so far. The most important (i.e. require too much creative alternative) is the impossibility to write to the .data section either from 32-bit or from 64-bit (I thought it was only 64-bit but is from both).


OPTION FLAT:1
; Some features of LITERALS:ON do not work with FLAT:1, See examples at the bottom
OPTION LITERALS:ON

USE32 ; USE32 is required to be here, otherwise the stack will be incorrectly restored after INVOKE printf
includelib \masm32\lib\msvcrt.lib
printf proto C :ptr,:vararg

.data
msg db "Received: 0x%.8x%.8x",10,0
somevalue dd 0 ; Can't write to .data either from 32-bit or 64-bit. And if we don't initialize values it believes it is a BSS segment

; Default Prologue and Epilogue do not work properly.
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
X64_Start macro
USE32
push 33h
call @F
@@:
add dword ptr [esp], @F-$
retf
@@:
USE64
endm

X64_End MACRO
USE64
    call   @F
@@:
    mov dword ptr [rsp + 4], 23h
    add dword ptr [rsp], @F-@B
    retf
@@:
USE32
ENDM

.code
main proc C
mov somevalue, 10 ; Writing to .data do not work either in 32-bit or 64-bit
X64_Start
; do something in 64-bit
X64_End
mov eax, 1
mov edx, 2
;invoke printf, CSTR("Received: 0x%.8x%.8x"),edx, eax ; does not work
;printf("Received: 0x%.8x%.8x",edx, eax ) ; does not work
invoke printf, offset msg, edx, eax
        ret
main endp

end

COMMENT #
Build with:
\masm32\bin\uasm64  -c -coff test.asm
\masm32\bin\link /entry:main /MACHINE:X86 /FIXED test.obj
#

Title: Re: USE directive error
Post by: johnsa on June 12, 2019, 01:32:20 AM
Bugs in general or if you're trying to use it to create a PE?

If in general I'll add a list to the 2.49 update of fixes.
Title: Re: USE directive error
Post by: aw27 on June 12, 2019, 01:43:20 PM
I did not explore properly PE creation using the new features of UASM. I made that small example but expanding on it proved difficult when compared with previous inroads - namely here: http://masm32.com/board/index.php?topic=6601.0

Now, I am working on dynamic processor mode switching, namely the Heaven's Gate. As mentioned, we can work with the bugs, but is difficult to explain to others that we are using a memory mapped file to write data because the .data section does not allow writing (allows reading, though).

In the following code I show that exists a possibility to have write access to a data section, if we don't call it .data.  :tongue:, by using indirect addressing  :rolleyes:


OPTION FLAT:1

USE32
.data
somevalue1 dd 0

_DATA2 SEGMENT PARA PUBLIC 'DATA'
somevalue2 dd 0
_DATA2 ENDS

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
X64_Start macro
USE32
push 33h
call @F
@@:
add dword ptr [esp], @F-$
retf
@@:
USE64
endm

X64_End MACRO
USE64
    call   @F
@@:
    mov dword ptr [rsp + 4], 23h
    add dword ptr [rsp], @F-@B
    retf
@@:
USE32
ENDM

USE32
.code
main proc C

; **** WRITING ***
;1- Does not work
;mov somevalue1, 1 ; crash

;2- Does not work
;lea edi, somevalue1
;mov dword ptr [edi], 1 ; crash

;3- Does not work
; mov somevalue2, 1 ; Can not access label

;4- Works
lea edi, somevalue2
mov dword ptr [edi], 1 ; works

; **** READING ***
;1- Works
mov eax, somevalue1

;2- Does not work
;mov eax, somevalue2 ; Can not access label

;3- Works
lea edi, somevalue2
mov eax, [edi]

;4- Works
lea edi, somevalue1
mov eax, [edi]

X64_Start

; **** WRITING ***
;1 - Does not work
;mov somevalue1, 1 ; crashes

;2 - Does not work
;lea rdi, somevalue1
;mov dword ptr [rdi], 1 ; crash

;3 - Does not work
;mov somevalue2, 1 ; Can not access label

;4- Works
lea rdi, somevalue2
mov dword ptr [rdi], 1 ; works

; **** READING ***
;1- Works
mov eax, somevalue1

;2- Does not work
;mov eax, somevalue2 ; Can not access label

;3- Works
lea rdi, somevalue2
mov eax, [rdi]

;4- Works
lea rdi, somevalue1
mov eax, [rdi]

X64_End

ret
main endp

end

COMMENT #
Build with:
\masm32\bin\uasm64  -c -coff test.asm
\masm32\bin\link /entry:main /MACHINE:X86 /FIXED test.obj
#



Something interesting, when we add a second DATA section the .data becomes .rdata (may be this is its true personality)

Dump of file test.exe

File Type: EXECUTABLE IMAGE

  Summary

        1000 .rdata
        1000 _DATA2
        1000 _flat