The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: wanker742126 on September 04, 2024, 05:35:02 PM

Title: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 04, 2024, 05:35:02 PM
I was writing a 64-bit Windows program and noticed something strange:
The following program can be successfully assembled using ML64, but will appear when using UASM64
"Error A2031: invalid addressing mode with current CPU setting"
--------------------------------------------------
array DD 20h DUP (1)
... ...
mov rcx,2
mov eax,array[rcx*4+8]
--------------------------------------------------
Does anyone know what's going on?
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: six_L on September 04, 2024, 09:18:43 PM
Hi,wanker742126
lea    rdx,array    ;mov    rdx,offset array
mov    rcx,2
mov    eax,[rdx+rcx*4]

rdx: the frist address of  your array
rcx: index
4: 1"DD"=4"BYTE"
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 04, 2024, 10:17:47 PM
Hello Six_L
I know it can be written like this, but I would like to know why ML64 can be successfully assembled, but UASM64 cannot. Is it necessary to make any settings on the CPU?
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: _japheth on September 04, 2024, 10:22:16 PM
Quote from: wanker742126 on September 04, 2024, 10:17:47 PMI know it can be written like this, but I would like to know why ML64 can be successfully assembled, but UASM64 cannot. Is it necessary to make any settings on the CPU?

No. It's valid syntax, and if UASM refuses it, it's a bug.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: six_L on September 04, 2024, 11:06:12 PM
Hi,wanker742126
Quotewhy ML64 can be successfully assembled, but UASM64 cannot. Is it necessary to make any settings on the CPU?
1,ML64 is written by microsoft; UASM64 is written by John Hankinson and Branislav Habus, _japheth (our forum member). they are different assembler.
2,Assembly language syntax of ML64 is not ml32-compatible, don't support HLL features. But UASM64 does.
3,ML64 only works on MS OS; UASM64 can work on MS OS, Linux and OSX.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 04, 2024, 11:15:08 PM
Thanks for your answer, six_L and _japheth.
Maybe I have to wait until UASM supports this syntax. Or maybe try using macros.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: six_L on September 04, 2024, 11:42:03 PM
Hi,wanker742126
QuoteMaybe I have to wait until UASM supports this syntax.
Maybe You will never be the outcome. because the register addressing is faster than the memory addressing.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: mineiro on September 05, 2024, 11:24:11 AM
;this is a simple workaround, tested in linux
;I was trying to create a macro but displacement have not been added to array offset
;so I put displacement in a register
mov rcx,2
mov edx,8
mov eax,array[ecx*sizeof dword+edx]

;+8 displacement is not being added
mov eax,array[rcx*sizeof dword+8+rdx]      ;<---
USE32
mov eax,dword ptr [array+8+ecx*4]         ;<---
USE64
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 07, 2024, 12:36:58 AM
Today I found that ADD, SUB, MUL, and DIV can all accept array usage, but only MOV cannot.
The following program can be successfully assembled using UASM64
OPTION  CASEMAP:NONE
OPTION  WIN64:3

INCLUDELIB      KERNEL32.LIB
INCLUDELIB      USER32.LIB

MessageBoxA     PROTO   :QWORD,:QWORD,:QWORD,:DWORD
ExitProcess     PROTO   :DWORD
;*********************************************************************
.CONST
array           DD      20h DUP (1)
szCaption       DB      "TITLE",0
szText          DB      "64-BIT ASSEMBLY.",0
;*********************************************************************
.CODE
;---------------------------------------------------------------------
main    PROC
        mov     rcx,2
        add     eax,array[rcx*4+8]
        sub     eax,array[rcx*4+8]
        xor     eax,array[rcx*4+8]
        mul     array[rcx*4+8]
        div     array[rcx*4+8]
        invoke  MessageBoxA,0,OFFSET szText,OFFSET szCaption,0
        invoke  ExitProcess,0
main    ENDP
;*********************************************************************
END     main


But the program below will fail to assemble and compile, and the error occurs in the MOV line.
OPTION  CASEMAP:NONE
OPTION  WIN64:3

INCLUDELIB      KERNEL32.LIB
INCLUDELIB      USER32.LIB

MessageBoxA     PROTO   :QWORD,:QWORD,:QWORD,:DWORD
ExitProcess     PROTO   :DWORD
;*********************************************************************
.CONST
array           DD      20h DUP (1)
szCaption       DB      "TITLE",0
szText          DB      "64-BIT ASSEMBLY.",0
;*********************************************************************
.CODE
;---------------------------------------------------------------------
main    PROC
        mov     rcx,2
        mov     eax,array[rcx*4+8]
        add     eax,array[rcx*4+8]
        sub     eax,array[rcx*4+8]
        xor     eax,array[rcx*4+8]
        mul     array[rcx*4+8]
        div     array[rcx*4+8]
        invoke  MessageBoxA,0,OFFSET szText,OFFSET szCaption,0
        invoke  ExitProcess,0
main    ENDP
;*********************************************************************
END     main

Title: Re: Use the MOV instruction to obtain the value in the array
Post by: six_L on September 07, 2024, 05:30:58 PM
you are digging the bugs of compiler, not learning the assembler language.
Come on!
the TAIWAN's frog is sitting on well and talking the vastness of sky.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 13, 2024, 05:58:04 PM
I wrote a set of macros that can somewhat resolve the issue of assembling instructions like mov eax, array[rcx*4+8] using UASM64.EXE. The principle is quite simple: analyze such instructions and convert them into the corresponding machine code. However, the implementation is rather complicated. Nonetheless, I managed to complete it.

Below is a demonstration program:

asm

OPTION  CASEMAP:NONE
OPTION  WIN64:3
INCLUDELIB      KERNEL32.LIB
INCLUDELIB      USER32.LIB
EXTRN   MessageBoxA:PROC
EXTRN   ExitProcess:PROC
INCLUDE MYFIX_ENG.INC
;*********************************************************
.DATA
button          DD      10h,20h,30h,40h
n               DD      4
szCaption       DB      "TEST MYFIX_ENG.INC",0
szText          DB      "PLEASE PRESS ANY BUTTON.",0
;*********************************************************
.CODE
;---------------------------------------------------------
main    PROC
again:  xor     rcx,rcx
        mov     rdx,OFFSET szText
        lea     r8,szCaption
        movzx   rax,WORD PTR n
        mova    r9d,button[rax*4]
        call    MessageBoxA
        dec     n
        jnz     again
        xor     ecx,ecx
        call    ExitProcess
main    ENDP
;*********************************************************
END

The mova macro used here is defined in MYFIX_ENG.INC. I've tested it, and it works fine, but there may still be oversights. If you encounter any issues, please let me know on the forum or via email: wkochih@gmail.com. Since MYFIX_ENG.INC has over 400 lines, I've compressed it into an archive.Here is MYFIX_ENG (https://mega.nz/file/sM1yXQIB#JcAJMwC5IMSLU9j2VONeRry0VukWByS5fmwhk5Jw4lU)
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: _japheth on September 14, 2024, 03:53:49 AM
Hello,

Your MYFIX_ENG.INC file is pretty large. Are you sure it works with any image base? I'm asking because I vaguely remember that RIP-relative addressing is limited to direct addressing - that means, if indirect addressing is used ( based or indexed or both ), the displacement ( = offset ) is always "zero-based", never RIP-relative. As a consequence, base/indexed addressing with displacements fully work in the first 4 GB of the address space only. However, it's long ago that I examined this stuff, maybe I'm wrong...
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 14, 2024, 10:31:34 AM
My MYFIX_ENG.INC can only be used in
MOV reg1,VAR[reg2*n]
MOV VAR[reg1*n],reg2
MOV Var[reg*n],imm
In three cases, reg1, reg2, and reg can only be general purposes registers, cannot be RIP. In fact, RIP cannot change its value through MOV. In addition, I also admit that MYFIX_ENG.INC is very large, with more than 400 lines, so I did not list the entire code on the forum, but downloaded its link through MEGA. Maybe you experts can simplify it :).
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: _japheth on September 14, 2024, 12:27:31 PM
Quote from: wanker742126 on September 14, 2024, 10:31:34 AMMy MYFIX_ENG.INC can only be used in
MOV reg1,VAR[reg2*n]

Ok, I did a little test:

.x64
.model flat
include MYFIX_ENG.INC

.data
db 50h dup (?)
array dd 0,1,2,3,4,5,6,7

.code
start:
xor ecx, ecx
mova eax, array[rcx*4]
mov eax, array[rcx*4]
ret
end  start

Since UASM refuses indexed addressing with symbolic displacement, I used JWasm to assemble it. DUMPBIN then displays the following relocations:

Offset    Type              Applied To         Index     Name
 --------  ----------------  -----------------  --------  ------
 00000005  ADDR32                     00000050         4  .data
 0000000C  ADDR32                     00000000         9  array

So there's indeed a difference, but the important thing is that both relocs are ADDR32. This inevitably makes  MS link complain:

Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

MOV64b.obj : error LNK2017: 'ADDR32' relocation to '.data' invalid without /LARGEADDRESSAWARE:NO
MOV64b.obj : error LNK2017: 'ADDR32' relocation to 'array' invalid without /LARGEADDRESSAWARE:NO
LINK90 : fatal error LNK1165: link failed because of fixup errors
[/code]

Of course, adding /LARGEADDRESSAWARE:NO to link's cmdline makes the errors disappear, but the image is then restricted to run in the first 4 GB of the address space.




Title: Re: Use the MOV instruction to obtain the value in the array
Post by: wanker742126 on September 14, 2024, 01:19:50 PM
In fact, I just hope that UASM64.EXE can assembly the following three situations:
MOV reg1,VAR[reg2*n]
MOV VAR[reg1*n],reg2
MOV Var[reg*n],imm
I didn't expect to be able to use the entire 64-bit addressing space. So I have always misunderstood your question.
Title: Re: Use the MOV instruction to obtain the value in the array
Post by: johnsa on March 13, 2025, 03:07:36 AM
You are wanting something that simply isn't possible.
You're either violating PE and address-space constraints or trying to hack in 32bit code-gen into 64bit mode.

var[base+idx*scale] addressing is fully supported in 32bit mode.

it should NEVER be used in 64bit code as even when the relocation is generated it won't be compatible with PE without adding LARGEADDRESSAWARE:NO - which is a terrible idea for many reasons.

You won't find this addressing form generated by any 64bit compiler (ie. C/C++) for this reason. It also prevents the addressing from being fully RIP relative. The accepted practice in 64bit code is to use LEA and then register_base+idx*scale.

lea rdi, myArray        ; RIP relative.
mov eax, [rdi+rcx*4]

I believe NASM can generate RIP relative references like:
mov eax, [rel myArray + rcx*4]
but I'm not sure if that actually solves the L.A.W. problem as it's simply not encodable in x64. I think the only form that would work is with a fixed constant like:
mov eax, [rel myArray + 10] as the ONLY addressing mode with RIP that x64 can handle is [RIP + ofs]

See:
https://stackoverflow.com/questions/48124293/can-rip-be-used-with-another-register-with-rip-relative-addressing (https://stackoverflow.com/questions/48124293/can-rip-be-used-with-another-register-with-rip-relative-addressing)
https://stackoverflow.com/questions/34058101/referencing-the-contents-of-a-memory-location-x86-addressing-modes (https://stackoverflow.com/questions/34058101/referencing-the-contents-of-a-memory-location-x86-addressing-modes)