News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Structure to Structure Copy

Started by Biterider, January 19, 2020, 03:29:03 AM

Previous topic - Next topic

Biterider

Hi
When I work on larger projects, it often happens that I have to copy structures such as POINT or RECT or larger ones. If the structures are not very large, the most efficient way to accomplish this task is to use the available registers. For example, if you are in the 64-bit world and need to copy a POINT structure, using a 64-bit register, in which both SDWORDs are copied at once, is the smartest method. The same operation in 32-bit requires 2 registers to load the values from the source structure into them and then store the values in the target structure. If only 1 register is available, the process must be unrolled reusing this register.

The other aspect is that structures can take on different sizes, so a combination of register sizes must be used to match the correct length.
Taking these basic requirements into account, I designed for my convenience a strategy that I implemented into a macro called s2s (structure-to-structure copy). It can be viewed as a relative of m2m or mrm macros.

The syntax looks like this:
local Rect1:RECT, Rect2:RECT
...
s2s Rect1, Rect2, rax, rcx
...

In the background, the $SubReg macro is used to select the correct register sizes. In this way, s2s can be used without changes in 32- and 64-bit code.

A user-friendly syntax for bitness-independent code that also works could be:
s2s Rect1, Rect2, xax, xcx

These macros are part of the upcoming ObjAsm system.inc file. I have put them together for a preview in the attached file. If the code is useful to someone, feel free to use or improve it.  :biggrin:

Regards, Biterider

jj2007

#1
Don't forget movlps, movups and fld :cool:

include \masm32\include\masm32rt.inc
include StructCopy.inc
.686p
.xmm

.data
pan1 PANOSE <10, 11, 12, 13, 14, 15, 16, 17, 18, 19>
pan2 PANOSE <?>
pt1 POINT <100, 200>
pt2 POINT <?>
rc1 RECT <10, 20, 30, 40>
rc2 RECT <?>

.code
start:
  StructCopy pan2, pan1
  movsx eax, pan2.bFamilyType
  print str$(eax), 9, " bFamilyType", 13, 10
  movsx eax, pan2.bXHeight
  print str$(eax), 9, " bXHeight", 13, 10

  StructCopy pt2, pt1
  mov eax, pt2.x
  print str$(eax), 9, " x", 13, 10
  mov eax, pt2.y
  print str$(eax), 9, " y", 13, 10

  StructCopy rc2, rc1
  print str$(rc2.left), 9, " left", 13, 10
  print str$(rc2.bottom), 9, " bottom", 13, 10
  exit

end start

HSE

Hi Biterider!

Quote from: Biterider on January 19, 2020, 03:29:03 AM
.. a macro called s2s (structure-to-structure copy). It can be viewed as a relative of m2m or mrm macros.

Impressive!
A lot more complex than my 32bit macro  :biggrin: CargaStruct macro tipo_de_objeto, ObjectDest, ObjectOrig
push esi
cld
mov edi, &ObjectDest;[Dest]
        mov esi, &ObjectOrig
        mov ecx , sizeof &tipo_de_objeto;[ln]
          rep movsb
pop esi
endm


I think you can create a similar macro for o2o in same way i have modified the previous macro:CopiaObjeto macro tipo_de_objeto, ObjectDest, ObjectOrig
push esi
cld
mov edi, &ObjectDest;
add edi , 16
mov esi, &ObjectOrig
add esi, 16
mov ecx , sizeof &tipo_de_objeto;
    sub ecx , 16
    rep movsb
pop esi
endm


And i used, for example: lea edx, dietaJenkins    ; Independent object
lea eax, [esi].Feed    ; Embedded object
CopiaObjeto MollyDiet, <eax>, <edx>


Regards. HSE
Equations in Assembly: SmplMath

Biterider

Hi HSE
Good to hear from you again!

Since the memory structure of an object is much larger than e.g. a RECT, I'm inclined to think that your macro is more efficient in terms of speed.  :thumbsup:
In the Objects.inc is something similar in the New implementation.

Regards, Biterider

HSE

Perfect  :thumbsup:

That can improve my macros.

Thanks.
Equations in Assembly: SmplMath

jj2007

Hi Biterider,

I wanted to get some timings, but your macro throws errors... what's wrong?

include \masm32\include\masm32rt.inc ; plain Masm32
iterations=99999999  ; 100 Mio
include StructCopy.inc
include S2S.inc
.686p
.xmm

.data
pan1 PANOSE <10, 11, 12, 13, 14, 15, 16, 17, 18, 19>
pan2 PANOSE <?>
pt1 POINT <100, 200>
pt2 POINT <?>
rc1 RECT <10, 20, 30, 40>
rc2 RECT <?>

.code
start:
  xpan equ PANOSE ptr [ebx]

  push rv(GetTickCount)
  push iterations
  mov ebx, offset pan2
  .Repeat
; StructCopy xpan, pan1
StructCopy rc2, rc1
dec dword ptr [esp]
  .Until Sign?
  pop edx
  invoke GetTickCount
  pop ecx
  sub eax, ecx
  print str$(eax), " ticks for StructCopy", 13, 10

if 1
  push esi
  push edi
  push rv(GetTickCount)
  push iterations
  mov ebx, offset pan2
  .Repeat
TARGET_BITNESS=32
mov ecx, RECT/4
mov esi, offset rc1
mov edi, offset rc2
rep movsd
dec dword ptr [esp]
  .Until Sign?
  pop edx
  invoke GetTickCount
  pop ecx
  sub eax, ecx
  print str$(eax), " ticks for rep movsd", 13, 10
  pop edi
  pop esi
endif

if 0 ; chokes
  push rv(GetTickCount)
  push iterations
  mov ebx, offset pan2
  .Repeat
TARGET_BITNESS=32
s2s rc1, rc2, rax, rcx
dec dword ptr [esp]
  .Until Sign?
  pop edx
  invoke GetTickCount
  pop ecx
  sub eax, ecx
  print str$(eax), " ticks for s2s", 13, 10
endif

if 0
  StructCopy xpan, pan1
  movsx eax, pan2.bFamilyType
  print str$(eax), 9, " bFamilyType", 13, 10
  movsx eax, pan2.bXHeight
  print str$(eax), 9, " bXHeight", 13, 10

  StructCopy pt2, pt1
  mov eax, pt2.x
  print str$(eax), 9, " x", 13, 10
  mov eax, pt2.y
  print str$(eax), 9, " y", 13, 10

  StructCopy rc2, rc1
  print str$(rc2.left), 9, " left", 13, 10
  print str$(rc2.bottom), 9, " bottom", 13, 10
endif
  inkey "hit any key"
  exit

end start

HSE

I also have a problem with s2s (in $SubReg i think)

But my test of a little improved macro:CargaStruct macro tipo_de_objeto, ObjectDest, ObjectOrig
    push esi
    cld
    mov edi, &ObjectDest;[Dest]
    mov esi, &ObjectOrig
    $$SizetoCopy = sizeof( &tipo_de_objeto)
    mov ecx , $$SizetoCopy/@WordSize;[ln]
    if @WordSize eq 8
        if $$SizetoCopy ge 8
     rep movsq
        endif                                       ;;Copy all possible QWORDs
if ($$SizetoCopy and 4) eq 4
     movsd
endif
    else
        if $$SizetoCopy ge 4
            rep movsd                                       ;;Copy all possible DWORDs
        endif    
    endif
    if ($$SizetoCopy and 2) eq 2
        movsw
    endif
    if ($$SizetoCopy and 1) eq 1
        movsb
    endif
    pop esi
endm

(file corrected in my following post)
Equations in Assembly: SmplMath

Biterider

Hi
There are 2 things. First, ml is not able to handle large lines, so please use uasm. Second, the $Upper was missing, my fault.
The new attachment contains all macros and should work.  :rolleyes:

Biterider

Biterider


HSE

Everything Ok!
1762 ticks for StructCopy
858 ticks for CargaStruct
827 ticks for s2s
Equations in Assembly: SmplMath

jj2007

Works fine now :thumbsup:

203 ticks for StructCopy
889 ticks for rep movsd
203 ticks for s2s

Biterider

Hi
On my system (i7-4770K), the results are:

234 ticks for StructCopy
969 ticks for rep movsd
141 ticks for s2s


Biterider

nidud

#12
deleted

HSE

Confirmed!!

Nidud's machine have a mental problem with 32 bits  :biggrin:
Perhaps some problem in 64bit machine because @WordSize :cool:

Btw, some modifications for a fair test ( also I corrected the wrong destinations, and the same type of loop):

483 ticks for StructCopy
796 ticks for CargaStruct
312 ticks for s2s
312 ticks for mov


later: a new version
later2: removed a punishment to s2s
Equations in Assembly: SmplMath

nidud

#14
deleted