flat assembler
Message board for the users of flat assembler.

Index > Main > Memory to memory move [fasmg]

Author
Thread Post new topic Reply to topic
donn



Joined: 05 Mar 2010
Posts: 321
donn 15 Jun 2021, 06:40
Hi, is this legal? Line #3

I thought you were not supposed to be able to mov "memory" operands to memory operands, only registers to or from. Isn't this combination illegal, or is it because in fasmg things are necessarily more abstract?

Code:
        sub rsp, 8*14
        mov r9, vkImageMemoryBarrierRef
        mov qword [rsp+9*8], vkImageMemoryBarrierRef      ;r9   (THIS LINE)       ; const VkImageMemoryBarrier*       pImageMemoryBarriers
        mov qword [rsp+8*8], 1            ;  uint32_t                      imageMemoryBarrierCount,
        mov qword [rsp+7*8], 0            ; const VkBufferMemoryBarrier*   pBufferMemoryBarriers,
        mov qword [rsp+6*8], 0            ; uint32_t                       bufferMemoryBarrierCount,
        mov qword [rsp+5*8], 0            ; const VkMemoryBarrier*         pMemoryBarriers,
        mov qword [rsp+4*8], 0            ; uint32_t                       memoryBarrierCount,
        mov r9, 0                       ; VkDependencyFlags              dependencyFlags,
        mov r8, 4096                    ; VK_PIPELINE_STAGE_TRANSFER_BIT
        mov rdx, 4096                   ; VK_PIPELINE_STAGE_TRANSFER_BIT
        mov rbx, [cmdBuffer]
        mov rcx, [rbx]
        mov rbx, vkCmdPipelineBarrierProc
       ...
    


I get a successful assemble, but am unable to execute.


Code:
flat assembler  version g.izxz
5 passes, 4.9 seconds, 299606 bytes.
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.9
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.9
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
Microsoft (R) Incremental Linker Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.
User32.Lib(USER32.dll) : warning LNK4078: multiple '.text' sections found with different attributes (60101020)
obj : error LNK2017: 'ADDR32' relocation to '.data' invalid without /LARGEADDRESSAWARE:NO
LINK : fatal error LNK1165: link failed because of fixup errors
'' is not recognized as an internal or external command,
operable program or batch file.    


If I change the line to r9 (uncomment the r9 and replace the second operand with r9, it assembles AND runs fine. Maybe treating this operand as a fixed literal value is legal, would have to consult the x86 operand combo docs, but not sure why this fails to link then.
Post 15 Jun 2021, 06:40
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 15 Jun 2021, 07:47
vkImageMemoryBarrierRef is a 64-bit memory reference. There is no instruction which moves a literal 64-bit value except MOV REG,imm64. (I assume) The 32-bit value is being sign-extended (which is not valid in all cases) and then stored.

What is the base address of the executable? Do you have a relocation section? If you are just using the defaults then maybe fasmg is getting confused by the 32-bit base, but I don't think that should happen.

Just to be safe I'd set the base address to a 64-bit value.
Code:
format PE64 GUI 6.2 at 0x1'8000'0000    
...is the default that MS uses a lot. Will need to match segments of other objects you're linking.

Edit: fasmg doesn't set IMAGE_FILE_LARGE_ADDRESS_AWARE on object files and does support 32-bit relocations, so you could set /LARGEADDRESSAWARE:NO for your other object files? Which would be another option, but I don't recommend doing that.


Last edited by bitRAKE on 15 Jun 2021, 08:10; edited 1 time in total
Post 15 Jun 2021, 07:47
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 15 Jun 2021, 08:10
PUSH/POP are valid memory to memory moves.
Code:
push qword[address]    
Also MOVS:
Code:
mov rsi, from
mov rdi, to
movsq    
Post 15 Jun 2021, 08:10
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 15 Jun 2021, 08:12
Not for a immediate value, revolution.
He's using static structures and trying to pass their address.
Post 15 Jun 2021, 08:12
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 15 Jun 2021, 08:15
You can also have immediate to memory:
Code:
mov [address], immediate_value    
Is that what the OP is asking about?
Post 15 Jun 2021, 08:15
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 15 Jun 2021, 08:35
Maybe, I'm wrong, but it seems like he's asking why this line is a problem:
Code:
mov qword [rsp+9*8], vkImageMemoryBarrierRef    
vkImageMemoryBarrierRef is a 64-bit pointer to static data - which means at assemble time it can be an immediate value. The linker output indicates that it's being assigned a ADDR32 relocation. Which is only valid when there is no chance for the program to be relocated in high memory (i.e. /LARGEADDRESSAWARE:NO). The other objects must have the flag set for there to be a conflict because fasmg doesn't set the flag by default - just checked.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 15 Jun 2021, 08:35
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 15 Jun 2021, 17:13
It might be helpful if \fasmg\packages\x86\include\format\coffms.inc, Line:620, had a check for IMAGE_FILE_LARGE_ADDRESS_AWARE and dis-allow ADDR32 type relocations. Which is important because object files always have relocation information, and even if the RVA is 32-bit the relocation is technically invalid when IMAGE_FILE_LARGE_ADDRESS_AWARE is set.

There isn't any error with fasmg - it's just easy to shoot yourself in the foot, but isn't that the way assembly is? This is because the current MS64 COFF settings only support IMAGE_FILE_LARGE_ADDRESS_AWARE not being set - which is opposite the PE64 settings.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 15 Jun 2021, 17:13
View user's profile Send private message Visit poster's website Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 15 Jun 2021, 23:09
Interesting, yeah was just curious not blocked, my use case is perfectly acceptable with a register (r9) as the source operand. And it even seems more proper.

Yeah meant this line:

Code:
mov qword [rsp+9*8], vkImageMemoryBarrierRef      ;r9   (THIS LINE)      


And interesting regarding the valid mem to mem moves but I think these examples the operands are HIDDEN..! Not explicit operand, per se.

The format I'm using is MS COFF which I'm linking, maybe that's why somethings choking, since it can be linked in different ways.

OBJ sent to:
Code:
link /LARGEADDRESSAWARE /MACHINE:X64 /SUBSYSTEM:WINDOWS  /ENTRY:start file.obj... etc    


I think I want LARGEADDRESSAWARE, ran into issues with large data sets in the past if I recall.

On second look, is it possibly trying to assemble this instruction:

Code:
MOV reg/mem64, imm32 C7 /0 id Move a 32-bit signed immediate value to a 64-bit 
register or memory operand.    


So, taking this example:
Code:
         sub rsp, 8*14                                             ; LINE 1
        mov r9, vkImageMemoryBarrierRef      ; LINE 2
        mov qword [rsp+9*8], vkImageMemoryBarrierRef      ; LINE 3       ;r9   (THIS LINE)       ; const VkImageMemoryBarrier*       pImageMemoryBarriers
            


If I put the address in register r9 at LINE2, them moved it into LINE3, that could be instruction C7 with a 32 bit immediate I suppose, but there doesnt seem to be an instruction that allows 64 bit immediate here.

https://www.amd.com/system/files/TechDocs/24594.pdf Page 274

So it's assembling with a 32 bit operand AND using this as a 32 bit address EVERYWHERE which is invalid when linking?

https://docs.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-error-lnk2017?view=msvc-160

Eh, food for thought..!
Post 15 Jun 2021, 23:09
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 15 Jun 2021, 23:23
Full length 64-bit immediate values are only valid for register destinations.

If you write to a memory destination then only the shortened 32-bit sign-extended immediate values are possible.

Regarding the mem-to-mem instructions: It is unfortunate that the Intel mnemonics tend to hide a lot of things. This is the same for DIV, LOOP, AAA, etc., and every instruction that alters the flags. Just reading the mnemonics is not enough to see what an instruction does.
Post 15 Jun 2021, 23:23
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 15 Jun 2021, 23:24
donn wrote:
So it's assembling with a 32 bit operand AND using this as a 32 bit address EVERYWHERE which is invalid when linking?

https://docs.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-error-lnk2017?view=msvc-160
The only documented 32-bit address space in 64-bit is /LARGEADDRESSAWARE:NO, afaik. Other methods are relying on undocumented behavior of loader. Which is great because we get all the smaller code and fancy addressing we are familiar with. Which is bad because things are more complicated: GPU is using 64-bit addresses and external libraries expect 64-bit addresses. We choose our battles. Very Happy

My choice would be to set IMAGE_FILE_LARGE_ADDRESS_AWARE in format.inc, Line:310 (like it is for PE64) and remove relocation support for 32-bit in coffms.inc. That's the most flexible solution, imho. Or add a LARGE? flag if you're more ambitious. (This will result in your error line actually producing an error at assemble-time.)

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 15 Jun 2021, 23:24
View user's profile Send private message Visit poster's website Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 15 Jun 2021, 23:52
Think this topic makes 100% sense now, there is no 64-bit immediate source operand, why there is not is beyond me but prob not enough bits to fit it, and that's why there is no assembly error. BUT if I want an assembly error I can set it with what you just mentioned. Again, can't remember why I set largeaddressaware, remember specifically running out of memory years ago, after I hit alot of vertex data (about 1.2GB) and made a lot of tweaks.

Resolved.
Post 15 Jun 2021, 23:52
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 16 Jun 2021, 09:05
bitRAKE wrote:
My choice would be to set IMAGE_FILE_LARGE_ADDRESS_AWARE in format.inc, Line:310 (like it is for PE64) and remove relocation support for 32-bit in coffms.inc.
I think that coffms.inc should actually check for IMAGE_FILE_LARGE_ADDRESS_AWARE flag and only conditionally enable the 32-bit relocation support then.
Post 16 Jun 2021, 09:05
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4073
Location: vpcmpistri
bitRAKE 17 Jun 2021, 21:20
I haven't done a lot of testing of it, but do you think this would be sufficient?:
Code:
 else if COFF.MACHINE = IMAGE_FILE_MACHINE_AMD64

        calminstruction dword? value
+               check   COFF.CHARACTERISTICS and IMAGE_FILE_LARGE_ADDRESS_AWARE
+               jyes    large
                compute value, value
                check   ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
                jyes    addr32
                check   ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable
                jyes    addr32nb
+           large:
                check   ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE)
                jno     plain
                check   1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable
                jyes    rel32
            plain:    
I am correct in assuming control-flow instructions only need the REL* type relocations?

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 17 Jun 2021, 21:20
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.