My ASM attempt (Wilbert_v2 version).
I changed .s into .s{10} for a1 and a2.
This way always 10 characters are available.
If you use .s, you have to make sure yourself that the string is large enough to hold the result before you pass the string address.
Code: Select all
DisableDebugger
Global Dim vet1.i(100): Global Dim vet2.i(100)
Define.i i,j
Define.s{10} a1,a2
RandomSeed(0)
For i=0 To 100: vet1(i)=Random(10,1): vet2(i)=Random(10,1): Next
Procedure.s Year2011(*String1,qt.i,flag.i) ; String1 from 00 to 99 with spaces | qt = 2 to 50 = len(String1+1)/3 | flag= 1 in vet1() or 0 in vet2()
Protected Dim dr.i(21)
Protected.i i,j
Protected.s aux
For i=1 To qt
aux=PeekS(*String1+(i-1)*6,2): If flag: dr(vet1(Val(aux)))+1: Else: dr(vet2(Val(aux)))+1: EndIf
Next
For i=1 To 10: If dr(i)<>0: dr(11+j)=dr(i):j+1: EndIf: Next
SortArray(dr(),#PB_Sort_Ascending,11,10+j)
aux="": For i=1 To j: aux+Str(dr(10+i)): Next
ProcedureReturn aux
EndProcedure
Structure StringElement
StructureUnion
c.c[2]
n.l
EndStructureUnion
spacing.c
EndStructure
Procedure.s Today(*cval.StringElement,qt.i,i2.i)
Protected Dim dr.i(21)
Protected.i i,j,n
Protected.s aux
!mov r11, [p.a_dr]
!mov r8, [a_vet1]
!mov r9, [a_vet2]
!mov r13, [p.v_qt]
!l_loop1:
n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
If i2
!mov r14, [r8 + r10]
!add qword [r11 + r14 * 8], 1
Else
!mov r14, [r9 + r10]
!add qword [r11 + r14 * 8], 1
EndIf
*cval + 6
!sub r13, 1
!jnz l_loop1
i=0
!mov r13, 10
!l_loop2:
!add qword [p.v_i], 1
If dr(i)<>0: dr(11+j)=dr(i):j+1: EndIf
!sub r13, 1
!jnz l_loop2
SortArray(dr(),#PB_Sort_Ascending,11,10+j)
aux="": For i=1 To j: aux+Str(dr(10+i)): Next
ProcedureReturn aux
EndProcedure
Procedure.s NewIdea(*cval.StringElement,qt.i,i2.i)
Protected Dim dr.i(21)
Protected.i i,j,n
Protected.s aux
!mov r11, [p.a_dr]
!mov r8, [a_vet1]
!mov r9, [a_vet2]
!mov r13, [p.v_qt]
!l_loop1a:
n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
If i2
!mov r14, [r8 + r10]
!add qword [r11 + r14 * 8], 1
Else
!mov r14, [r9 + r10]
!add qword [r11 + r14 * 8], 1
EndIf
*cval + 6
!sub r13, 1
!jnz l_loop1a
i=0
!mov r13, 10
!l_loop2a:
!add qword [p.v_i], 1
dr(11+dr(i))+1: If dr(i)>j: j=dr(i): EndIf
!sub r13, 1
!jnz l_loop2a
aux="": For i=1 To j : aux+Str(dr(11+i)): Next
ProcedureReturn LSet(aux,10,"z")
EndProcedure
Procedure.s Wilbert(*cval.StringElement,*where,qt.i,i2.i)
Protected Dim dr.i(21)
Protected.i i,j,n
Protected.s aux
!mov r11, [p.a_dr]
!mov r8, [a_vet1]
!mov r9, [a_vet2]
!mov r13, [p.v_qt]
!l_loop1w:
n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
If i2
!mov r14, [r8 + r10]
!add qword [r11 + r14 * 8], 1
Else
!mov r14, [r9 + r10]
!add qword [r11 + r14 * 8], 1
EndIf
*cval + 6
!sub r13, 1
!jnz l_loop1w
i=0
!mov r13, 10
!l_loop2w:
!add qword [p.v_i], 1
dr(11+dr(i))+1: If dr(i)>j: j=dr(i): EndIf
!sub r13, 1
!jnz l_loop2w
For i=1 To j: PokeS(@where+(i-1)*2,Str(dr(11+i)),1): Next
ProcedureReturn
EndProcedure
Procedure Wilbert_v2(*StringIn, *FixedStringOut, qt.l, flag.l)
!mov r8, [p.p_StringIn]
!mov r9, [p.p_FixedStringOut]
!mov ecx, [p.v_qt]
!cmp dword [p.v_flag], 0
!cmovne r10, [a_vet1]
!cmove r10, [a_vet2]
; allocate some stack memory and clear first 16 bytes
!sub rsp, 272
!mov rdx, rsp
!pxor xmm0, xmm0
!movdqu [rdx], xmm0
; get number from string
!.l0:
!mov eax, [r8]
!and eax, 0xf000f
!imul eax, 0xa0001
!shr eax, 16
!add r8, 6
; lookup inside vet array
!movzx eax, byte [r10 + rax*8]
; increase value
!add byte [rdx + rax], 1
; next
!sub ecx, 1
!jnz .l0
; clear 16 bytes for count
!lea r8, [rdx + 16]
!movdqu [r8], xmm0
; count
!mov ecx, 10
!.l1:
!movzx eax, byte [rdx + rcx]
!add byte [r8 + rax], 1
!sub ecx, 1
!jnz .l1
; create output
!mov ecx, 10
!.l2:
!movzx eax, byte [r8 + rcx]
!cmp eax, 0
!jne .l4
!mov eax, 'z'; remove this line if you don't want 'z' padding
!mov [r9 + rcx*2 - 2], ax
!sub ecx, 1
!jnz .l2
!jmp .l5
!.l3:
!movzx eax, byte [r8 + rcx]
!.l4:
!add eax, '0'
!mov [r9 + rcx*2 - 2], ax
!sub ecx, 1
!jnz .l3
!.l5:
; restore stack pointer
!add rsp, 272
EndProcedure
String1.s="15 12 18 87 95 10 13 21 14 88 80 77 51 53 43 26 81 00 11"
t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again:
a1=Year2011(@String1,18,1)
a2=Year2011(@String1,18,0)
!sub r15, 1
!jnz l_again
Result$+"( In 2011 ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)
t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again1:
a1=Today(@String1,18,1)
a2=Today(@String1,18,0)
!sub r15, 1
!jnz l_again1
Result$+"( Today ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)
t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again2:
a1=NewIdea(@String1,18,1)
a2=NewIdea(@String1,18,0)
!sub r15, 1
!jnz l_again2
Result$+"( New idea ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)
t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again3:
Wilbert(@String1,@a1,18,1)
Wilbert(@String1,@a2,18,0)
!sub r15, 1
!jnz l_again3
Result$+"( Wilbert ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)
t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again4:
Wilbert_v2(@String1,@a1,18,1)
Wilbert_v2(@String1,@a2,18,0)
!sub r15, 1
!jnz l_again4
Result$+"( Wilbert_v2 ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)
EnableDebugger
Debug Result$