Author Topic: Structure to Structure Copy  (Read 1622 times)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Structure to Structure Copy
« on: January 19, 2020, 03:29:03 AM »
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:
Code: [Select]
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:
Code: [Select]
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

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Structure to Structure Copy
« Reply #1 on: January 19, 2020, 05:01:59 AM »
Don't forget movlps, movups and fld :cool:

Code: [Select]
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
« Last Edit: January 19, 2020, 06:15:36 AM by jj2007 »

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Structure to Structure Copy
« Reply #2 on: January 28, 2020, 02:06:25 AM »
Hi Biterider!

.. 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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
lea edx, dietaJenkins    ; Independent object
lea eax, [esi].Feed    ; Embedded object
CopiaObjeto MollyDiet, <eax>, <edx>

Regards. HSE

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Structure to Structure Copy
« Reply #3 on: January 28, 2020, 03:29:20 AM »
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

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Structure to Structure Copy
« Reply #4 on: January 28, 2020, 04:07:29 AM »
Perfect  :thumbsup:

That can improve my macros.

Thanks.

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Structure to Structure Copy
« Reply #5 on: January 28, 2020, 07:08:41 AM »
Hi Biterider,

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

Code: [Select]
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

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Structure to Structure Copy
« Reply #6 on: January 28, 2020, 08:31:42 AM »
I also have a problem with s2s (in $SubReg i think)

But my test of a little improved macro:
Code: [Select]
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)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Structure to Structure Copy
« Reply #7 on: January 28, 2020, 08:51:55 AM »
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

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Structure to Structure Copy
« Reply #8 on: January 28, 2020, 08:54:37 AM »
Hi HSE
 :thumbsup:

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Structure to Structure Copy
« Reply #9 on: January 28, 2020, 09:11:35 AM »
Everything Ok!
Code: [Select]
1762 ticks for StructCopy
858 ticks for CargaStruct
827 ticks for s2s

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Structure to Structure Copy
« Reply #10 on: January 28, 2020, 09:29:51 AM »
Works fine now :thumbsup:

Code: [Select]
203 ticks for StructCopy
889 ticks for rep movsd
203 ticks for s2s

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Structure to Structure Copy
« Reply #11 on: January 28, 2020, 05:37:43 PM »
Hi
On my system (i7-4770K), the results are:

Code: [Select]
234 ticks for StructCopy
969 ticks for rep movsd
141 ticks for s2s

Biterider

nidud

  • Member
  • *****
  • Posts: 1979
    • https://github.com/nidud/asmc
Re: Structure to Structure Copy
« Reply #12 on: January 29, 2020, 01:13:01 AM »
Memory operands are allowed in Asmc. This normally for reg-sized operands and includes MOV, CMP, TEST, ADC, ADD, SBB, SUB, AND, OR and XOR. It also allows unequal sized blocks to be moved.

Version 2.31.12 will move up to 16 bytes in 32-bit and 32 bytes in 64-bit. Anything above uses MOVSB.

203 ticks for StructCopy
3073 ticks for CargaStruct
172 ticks for s2s
140 ticks for mov pan1,pan2

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Structure to Structure Copy
« Reply #13 on: January 29, 2020, 02:52:10 AM »
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):

Code: [Select]
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

nidud

  • Member
  • *****
  • Posts: 1979
    • https://github.com/nidud/asmc
Re: Structure to Structure Copy
« Reply #14 on: January 29, 2020, 03:37:02 AM »

203 ticks for StructCopy
3073 ticks for CargaStruct
172 ticks for s2s
140 ticks for mov


It uses RAX, EAX, and AL for copy but AX is used otherwise.
Copy should be restricted to MOV only so this needs a fix.