Gå til innhold

Anbefalte innlegg

Gjest Slettet+9871234

Dette burde være av interesse for dere som jobber med Assembly generelt og i C++ spesielt. Det er enkelt å integrere inline assembly instruksjoner i C++Builder.

 

RAD Studio XE3 World Tour i Oslo

Oslo

13 september 2012

Håndverkeren Kurs- og Konferansesenter,

Rosenkrantzgate 7

0159 Oslo

 

Embarcaderos hjemmeside: http://www.embarcadero.com/

 

Jeg har fulgt C++ fra den var eid av Borland. Nå eies som kjent RAD Studio XE3 som inneholder C++Builder samt Delhi (Skype ble utviklet i Delphi) av Embarcadero.

Endret av Slettet+9871234
Lenke til kommentar
Videoannonse
Annonse

Min rot13 funksjon roterer strenger med en hastighet på 2,2 bytes per nano sekund (2,23 GB per sekund). Jeg har ikke forsøkt å optimalisere den videre ennå. Men se om du kan slå den først. Jeg har ikke anelse hvor dette ligger hen i forhold til et liknende c++ program, så jeg må bare se meg frem her. :hm:

 

 

Rot13Buf4  DB 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
 DB 27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50
 DB 51,52,53,54,55,56,57,58,59,60,61,62,63,64
 DB "NOPQRSTUVWXYZABCDEFGHIJKLM"
 DB 91,92,93,94,95,96
 DB "nopqrstuvwxyzabcdefghijklm"
 DB 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142
 DB 143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162
 DB 163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182
 DB 183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202
 DB 203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222
 DB 223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242
 DB 243,244,245,246,247,248,249,250,251,252,253,254,255
.CODE
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
ALIGN 16
Rot13L8 PROC
push ebx
push edi
xor ecx, ecx
xor edx, edx
mov edi, OFFSET Rot13Buf4
ALIGN 16
@@: mov eax, [esi]
mov ebx, [esi+4]
mov cl, al
mov dl, ah
mov cl, [edi+ecx]
mov dl, [edi+edx]
shr eax, 16
mov [esi], cl
mov [esi+1], dl
mov cl, al
mov dl, ah
mov [esi+2], cl
mov [esi+3], dl
mov cl, bl
mov dl, bh
mov cl, [edi+ecx]
mov eax, esi
mov dl, [edi+edx]
shr ebx, 16
add esi, 8
sub ebp, 1
mov [eax+4], cl
mov [eax+5], dl
mov cl, bl
mov dl, bh
mov [eax+6], cl
mov [eax+7], dl
jnz @B
pop edi
pop ebx
ret
Rot13L8 ENDP

Endret av LonelyMan
Lenke til kommentar

All respekt til deg, LonelyMan, som bruker Assembly på denne måten, men jeg kan ikke riste av meg følelsen at det er ganske bortkastet tid.

Her er Visual C++ sin output fra følgende kode. Mulig jeg har missforstått ROT-13, si ifra isåfall:

extern "C"
{
void Rot13_C(const char* input, const size_t size, char* output)
{
 for(auto i = 0; i < size; i++)
 {
  if((input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z'))
  {
   auto offset = input[i] >= 'a' && input[i] <= 'z' ? 'a' : 'A';
   output[i] = (char)((input[i] + 13) - offset) % ('z' - 'a') + offset;
  }
  else
   output[i] = input[i];
 }
 output[size] = 0;
}
}

 

Assembly output fra compileren:

Rot13_C PROC	  ; COMDAT
; 22   :  {
$LN19:
push rdi
; 23   :   for(auto i = 0; i < size; i++)
xor r10d, r10d
mov rdi, r8
mov r11, rdx
test rdx, rdx
je $LN17@Rot13_C
mov QWORD PTR [rsp+16], rbx
lea r9, OFFSET FLAT:??_C@_0EG@CHCBLGHC@A?5rotate?5buffer?5must?5be?5rotated?5@
mov rbx, r8
mov QWORD PTR [rsp+24], rsi
lea esi, QWORD PTR [r10+97]
sub rbx, r9
npad 1
$LL7@Rot13_C:
; 24   :   {
; 25   :    if((input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z'))
movzx eax, BYTE PTR [r9]
lea ecx, DWORD PTR [rax-97]
cmp cl, 25
jbe SHORT $LN3@Rot13_C
lea ecx, DWORD PTR [rax-65]
cmp cl, 25
jbe SHORT $LN3@Rot13_C
; 29   :    }
; 30   :    else
; 31   :	 output[i] = input[i];
mov BYTE PTR [rbx+r9], al
jmp SHORT $LN6@Rot13_C
$LN3@Rot13_C:
lea ecx, DWORD PTR [rax-97]
mov r8d, 65	 ; 00000041H
cmp cl, 25
cmovbe r8d, esi
; 26   :    {
; 27   :	 auto offset = input[i] >= 'a' && input[i] <= 'z' ? 'a' : 'A';
; 28   :	 output[i] = (char)((input[i] + 13) - offset) % ('z' - 'a') + offset;
sub al, r8b
add al, 13
movsx ecx, al
mov eax, 1374389535    ; 51eb851fH
imul ecx
sar edx, 3
mov eax, edx
shr eax, 31
add edx, eax
imul edx, 25
sub ecx, edx
add cl, r8b
mov BYTE PTR [rbx+r9], cl
$LN6@Rot13_C:
; 23   :   for(auto i = 0; i < size; i++)
inc r10d
inc r9
movsxd rax, r10d
cmp rax, r11
jb SHORT $LL7@Rot13_C
; 32   :   }
; 33   :   output[size] = 0;
mov rsi, QWORD PTR [rsp+24]
mov rbx, QWORD PTR [rsp+16]
mov BYTE PTR [r11+rdi], 0

 

På denne maskinen resulterte det i 14.7 bytes per nanosekund.

Lenke til kommentar
Gjest Slettet+9871234

Skulle gjerne sett ASM output fra siste versjon av RAD studio XE III C++ Builder.

 

P.S.

 

<off topic>

 

Dette

 

Embarcadero HTML5 Builder Revolutionizes Mobile and Web App Development

 

Here comes the iPhone 5

 

burde interessere noen av dere frontrunnere. Hva med assembly på iPhone5 og andre mobiltelefoner som jo ikke er noe annet enn en datamaskin, dog med svak sikkerhet.

</off topic>

Lenke til kommentar

Punkt 1: Du kjører 64 bits kode.

 

Punkt 2: 14,7 bytes per nanosekund er umulig for dagens datamaskiner. he-he

 

Det er en alvorlig feil en plass her ja. Det er garantert. :D

Ah jeg som hadde gjort feil men beregningen. Det var ikke i nærheten engang, 0.06 bytes per nanosekund :/

 

Men jeg kan vel med fordel bruke en lookup tabell slik som du gjør også.

Endret av GeirGrusom
Lenke til kommentar
Gjest Slettet+9871234

Skulle gjerne sett ASM output fra siste versjon av RAD studio XE III C++ Builder.

 

Visual C++ og GCC har ihvertfall flagg for å gi ifra seg assembly-kode til output, så går utifra at C++Builder har det samme.

 

Ja det er svært enkelt, men jeg har ikke siste versjon eller tid til å teste det på eldre versjoner.

Lenke til kommentar
Gjest Slettet+9871234

Det er utrolig hvor mye data man kan behandle samtidig med 64 bit registre. Jeg skal snart hoppe fra 32 bit for godt og begynne på 64 bit. Men da skal jeg begynne med JWasm istedet for Masm. Eventuelt Fasm.

 

Vil det si at segmenter fra 16 bits teknologi ikke lenger er aktuelt? Med andre ord, kan man spare tid på å blande 16, 32 og 64 bits teknologier som jeg var inne på tidligere eller er det uaktuelt med 64 bits teknologier.

 

Kanskje et dumt spørsmål, er der i analogi med mengdelære et indre snitt av instruksjoner som deler av et program kan kjøre på for å øke hastigjheten.

 

Nesten som i Drupal kjernen ... :huh:

Lenke til kommentar

Jeg får ut 2,72GB pr sekund...mer enn hva programmet skrevet i assembler fikk ut.

Men det kan jo være forskjell på prosessorene våre.

 

100MB går på 43 - 44ms.

Input er 100MB med random generert strings med både store og små bokstaver.

 

Prøv å kjør den hos deg.

 

(NB, jeg var lat når jeg laget koden for å time funksjonen min, så bruker den mer enn 1000ms skriver den ut rare verdier).

 

 

Assemlby output:

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
include listing.inc
INCLUDELIB OLDNAMES
PUBLIC ?lookup@@3PADA	 ; lookup
EXTRN __imp__time64:PROC
EXTRN __imp_rand:PROC
EXTRN __imp_srand:PROC
EXTRN __imp_getchar:PROC
EXTRN __imp_printf:PROC
EXTRN __imp_free:PROC
EXTRN __imp_malloc:PROC
EXTRN __imp_GetLocalTime:PROC
?lookup@@3PADA DB 0100H DUP (?)	; lookup
$SG-7 DB 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 00H
ORG $+3
$SG-8 DB '100 Megabytes took %d milliseconds.', 0aH, 00H
PUBLIC ?createLookup@@YAXXZ	; createLookup
; Function compile flags: /Ogtpy
_TEXT SEGMENT
?createLookup@@YAXXZ PROC	; createLookup
; File d:\projects\arraytester\arraytester\arraytester.cpp
; Line 27
xor eax, eax
lea rcx, OFFSET FLAT:?lookup@@3PADA  ; lookup
npad 7
$LL13@createLook:
; Line 28
mov BYTE PTR [rcx], al
inc eax
inc rcx
cmp eax, 256	; 00000100H
jl SHORT $LL13@createLook
; Line 31
mov ecx, 65	 ; 00000041H
lea rdx, OFFSET FLAT:?lookup@@3PADA+65
npad 6
$LL10@createLook:
; Line 33
lea eax, DWORD PTR [rcx+13]
cmp ecx, 77	 ; 0000004dH
jle SHORT $LN22@createLook
; Line 35
lea eax, DWORD PTR [rcx-13]
$LN22@createLook:
; Line 31
inc ecx
; Line 35
mov BYTE PTR [rdx], al
inc rdx
cmp ecx, 90	 ; 0000005aH
jle SHORT $LL10@createLook
; Line 39
mov ecx, 97	 ; 00000061H
lea rdx, OFFSET FLAT:?lookup@@3PADA+97
$LL5@createLook:
; Line 41
lea eax, DWORD PTR [rcx+13]
cmp ecx, 109	; 0000006dH
jle SHORT $LN23@createLook
; Line 43
lea eax, DWORD PTR [rcx-13]
$LN23@createLook:
; Line 39
inc ecx
; Line 43
mov BYTE PTR [rdx], al
inc rdx
cmp ecx, 122	; 0000007aH
jle SHORT $LL5@createLook
; Line 46
fatret 0
?createLookup@@YAXXZ ENDP	; createLookup
_TEXT ENDS
PUBLIC ?stringRotation@@YAXPEADH@Z   ; stringRotation
; Function compile flags: /Ogtpy
_TEXT SEGMENT
text$ = 8
?stringRotation@@YAXPEADH@Z PROC   ; stringRotation
; Line 22
inc rcx
mov edx, 20000000	; 01312d00H
lea r8, OFFSET FLAT:?lookup@@3PADA  ; lookup
npad 1
$LL3@stringRota:
movsx rax, BYTE PTR [rcx-1]
add rcx, 5
dec rdx
movzx eax, BYTE PTR [rax+r8]
mov BYTE PTR [rcx-6], al
movsx rax, BYTE PTR [rcx-5]
movzx eax, BYTE PTR [rax+r8]
mov BYTE PTR [rcx-5], al
movsx rax, BYTE PTR [rcx-4]
movzx eax, BYTE PTR [rax+r8]
mov BYTE PTR [rcx-4], al
movsx rax, BYTE PTR [rcx-3]
movzx eax, BYTE PTR [rax+r8]
mov BYTE PTR [rcx-3], al
movsx rax, BYTE PTR [rcx-2]
movzx eax, BYTE PTR [rax+r8]
mov BYTE PTR [rcx-2], al
jne SHORT $LL3@stringRota
; Line 24
fatret 0
?stringRotation@@YAXPEADH@Z ENDP   ; stringRotation
; Function compile flags: /Ogtpy
time PROC
; File d:\program files (x86)\microsoft visual studio 10.0\vc\include\time.inl
; Line 133
xor ecx, ecx
; Line 134
rex_jmp QWORD PTR __imp__time64
time ENDP
_TEXT ENDS
PUBLIC ?randomStrGen@@YAXPEADH@Z   ; randomStrGen
pdata SEGMENT
$pdata$?randomStrGen@@YAXPEADH@Z DD imagerel $LN10
DD imagerel $LN10+131
DD imagerel $unwind$?randomStrGen@@YAXPEADH@Z
pdata ENDS
xdata SEGMENT
$unwind$?randomStrGen@@YAXPEADH@Z DD 081401H
DD 086414H
DD 075414H
DD 063414H
DD 070103214H
; Function compile flags: /Ogtpy
xdata ENDS
_TEXT SEGMENT
str$ = 48
?randomStrGen@@YAXPEADH@Z PROC	; randomStrGen
; File d:\projects\arraytester\arraytester\arraytester.cpp
; Line 12
$LN10:
mov QWORD PTR [rsp+8], rbx
mov QWORD PTR [rsp+16], rbp
mov QWORD PTR [rsp+24], rsi
push rdi
sub rsp, 32	 ; 00000020H
mov rdi, rcx
; Line 14
xor ecx, ecx
call QWORD PTR __imp__time64
mov rcx, rax
call QWORD PTR __imp_srand
; Line 15
xor ebx, ebx
mov rsi, 5675921253449092805  ; 4ec4ec4ec4ec4ec5H
lea rbp, OFFSET FLAT:$SG-7
npad 5
$LL3@randomStrG:
; Line 16
call QWORD PTR __imp_rand
inc rbx
movsxd rcx, eax
mov rax, rsi
mul rcx
shr rdx, 4
imul rdx, 52	 ; 00000034H
sub rcx, rdx
movzx eax, BYTE PTR [rcx+rbp]
mov BYTE PTR [rbx+rdi-1], al
cmp rbx, 99999999	; 05f5e0ffH
jl SHORT $LL3@randomStrG
; Line 17
mov rbx, QWORD PTR [rsp+48]
mov rbp, QWORD PTR [rsp+56]
mov rsi, QWORD PTR [rsp+64]
add rsp, 32	 ; 00000020H
pop rdi
ret 0
?randomStrGen@@YAXPEADH@Z ENDP	; randomStrGen
_TEXT ENDS
PUBLIC main
EXTRN memset:PROC
pdata SEGMENT
$pdata$main DD imagerel $LN34
DD imagerel $LN34+316
DD imagerel $unwind$main
pdata ENDS
xdata SEGMENT
$unwind$main DD 040a01H
DD 0a340aH
DD 07006720aH
; Function compile flags: /Ogtpy
xdata ENDS
_TEXT SEGMENT
before$ = 32
after$ = 48
argc$ = 80
argv$ = 88
main PROC
; Line 49
$LN34:
mov QWORD PTR [rsp+8], rbx
push rdi
sub rsp, 64	 ; 00000040H
; Line 53
mov ecx, 100000000	; 05f5e100H
call QWORD PTR __imp_malloc
; Line 54
xor edx, edx
mov r8d, 100000000	; 05f5e100H
mov rcx, rax
mov rbx, rax
call memset
; Line 55
mov rcx, rbx
call ?randomStrGen@@YAXPEADH@Z  ; randomStrGen
lea rdi, OFFSET FLAT:?lookup@@3PADA  ; lookup
; Line 59
xor r11d, r11d
mov rcx, rdi
npad 3
$LL15@main:
mov BYTE PTR [rcx], r11b
inc r11d
inc rcx
cmp r11d, 256	; 00000100H
jl SHORT $LL15@main
mov ecx, 65	 ; 00000041H
lea rdx, OFFSET FLAT:?lookup@@3PADA+65
npad 2
$LL12@main:
lea eax, DWORD PTR [rcx+13]
cmp ecx, 77	 ; 0000004dH
jle SHORT $LN32@main
lea eax, DWORD PTR [rcx-13]
$LN32@main:
inc ecx
mov BYTE PTR [rdx], al
inc rdx
cmp ecx, 90	 ; 0000005aH
jle SHORT $LL12@main
mov ecx, 97	 ; 00000061H
lea rdx, OFFSET FLAT:?lookup@@3PADA+97
$LL7@main:
lea eax, DWORD PTR [rcx+13]
cmp ecx, 109	; 0000006dH
jle SHORT $LN33@main
lea eax, DWORD PTR [rcx-13]
$LN33@main:
inc ecx
mov BYTE PTR [rdx], al
inc rdx
cmp ecx, 122	; 0000007aH
jle SHORT $LL7@main
; Line 63
lea rcx, QWORD PTR before$[rsp]
call QWORD PTR __imp_GetLocalTime
lea r11, QWORD PTR [rbx+1]
mov ecx, 20000000	; 01312d00H
npad 2
; Line 65
$LL20@main:
movsx rax, BYTE PTR [r11-1]
add r11, 5
dec rcx
movzx eax, BYTE PTR [rax+rdi]
mov BYTE PTR [r11-6], al
movsx rax, BYTE PTR [r11-5]
movzx eax, BYTE PTR [rax+rdi]
mov BYTE PTR [r11-5], al
movsx rax, BYTE PTR [r11-4]
movzx eax, BYTE PTR [rax+rdi]
mov BYTE PTR [r11-4], al
movsx rax, BYTE PTR [r11-3]
movzx eax, BYTE PTR [rax+rdi]
mov BYTE PTR [r11-3], al
movsx rax, BYTE PTR [r11-2]
movzx eax, BYTE PTR [rax+rdi]
mov BYTE PTR [r11-2], al
jne SHORT $LL20@main
; Line 68
lea rcx, QWORD PTR after$[rsp]
call QWORD PTR __imp_GetLocalTime
; Line 71
movzx r11d, WORD PTR before$[rsp+14]
movzx edx, WORD PTR after$[rsp+14]
lea rcx, OFFSET FLAT:$SG-8
sub edx, r11d
call QWORD PTR __imp_printf
; Line 74
call QWORD PTR __imp_getchar
; Line 75
mov rcx, rbx
call QWORD PTR __imp_free
; Line 77
mov rbx, QWORD PTR [rsp+80]
xor eax, eax
add rsp, 64	 ; 00000040H
pop rdi
ret 0
main ENDP
_TEXT ENDS
END

ArrayTester.zip

Endret av Drogin
Lenke til kommentar
Gjest Slettet+9871234

  1. Hva er det man egentlig tester her?
  2. Gjentatte identiske operasjoner med ulik input?
  3. Hvor godt er det i så fall egnet til å teste det man egentlig skal teste slik jeg har forstått problemstillingen?
  4. Er der mønstre i din kode, burde LonelyMan kunne benytte det til å lage en mer effektiv kode.
  5. Hvis man tester gjentatte identiske operasjoner, hvor godt egnet er det til å teste om en assembly programmere er bedre enn en optimaliserende moderne kompilator?
  6. En presisering av oppgaven hadde gjerne vært på sin plass.
  7. Det er selvsagt helt fundamentalt at kodene testes på samme datamaskin. Der er forskjell på en isomorfi og en polymorfi.

Endret av Slettet+9871234
Lenke til kommentar
Gjest Slettet+9871234

Det ser riktig ut Drogin, men dog 64 bit (jeg bruker 32 bit)

 

Da bruker man vel strengt tatt ulik underliggende platform. Blir spennende å se din eventuelle 64 bits løsning. Det forundrer vel heller ingen at en kompilator kan slå en ASM programmerer på deler av en kode. Da er spørsmålene

  1. Hvor komplesk er koden i betydningen ikke repeterende instruksjoner (som vel kan puttes i en sub rutine)?
  2. Kan programmereren studere ASM output fra kompilatoren og forbedre sin kode der den er mindre effektiv?
  3. Kan kompilatoren gjøre det samme?
  4. Er der noe for en programmerer å vinne på reverse engineering (disassemblering) av C / C++ exe koden med flere pass gjennom koden?

Endret av Slettet+9871234
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...