Re: Konverzió!!!!

Andras Tantos andras at tantosonline.com
Tue Sep 27 17:28:26 CEST 2005


> Khm.. nem szorozgatunk 8-cal meg kettovel, mert az bonyi.... matematikus 
> varazslas... elb..od..
>
> Ha fix 3 helyiertek van, akkor egyszeruen a legmagasabbnal egy 16 bites 
> osszeadassal hozzaadsz ciklusban annyiszor 100-at (064H) amellyi binarisod 
> maradt a pozicion a 030H ascii levagasa utan...
> Aztan a kovetkezo pozicio mint szamlalo 0AH val ciklusban, aztan ha 
> perverz vagy szinten ciklusban 1-et, de ezt mar magaban is hozza lehet 
> adni...:-)
>
> Ennel eccerubb es eronthatatlanabb kodolas nemletezik...
> De elegansabb az bizonyara, csak az konnyebb elrontani...
> Es aprogramban mashol meg ezer helyen elronthatod, minek ezzel is szivatni 
> magad.... en legalabbis nem szoktam...:-)
>

Hmm...

Megirtam mindkettot (igaz C-ben). Annyit valtoztattam, hogy nem fejtem ki a 
ciklust minden egyes jegyre. Nos, remelem azt kodoltam le, amit gondoltal (a 
Conv2 lenne az altalad javasolt megvalositas, illetve a Conv3 a tied, de 
kulon leirva minden szamjegy konverzioja):

#include <stdio.h>

int Conv1(const char *aStr) {
 int Num = 0;

 while(*aStr != 0) {
  Num = (Num << 3) + (Num << 1) + *aStr - '0';
  ++aStr;
 }
 return Num;
}

int Conv2(const char *aStr) {
 int Num = 0;
 const int CoefArray[] = {100,10,1};
 const int *Coef = CoefArray;
 while (*aStr != 0) {
  for(int i=*aStr-'0';i>0;--i) {
   Num += *Coef;
  }
  ++aStr;
  ++Coef;
 }
 return Num;
}

int Conv3(const char *aStr) {
 int Num = 0;
 for(int i=aStr[0]-'0';i>0;--i) {
  Num += 100;
 }
 for(int i=aStr[1]-'0';i>0;--i) {
  Num += 10;
 }
 Num += aStr[2]-'0';
 return Num;
}

void main() {
    char *Str = "123";
    printf("From %s to %d or %d or 
%d\n",Str,Conv1(Str),Conv2(Str),Conv3(Str));
}

Nem tudom, kinek melyik a bonyolultabb, de nezzuk mit csinal a fordito 
(VC++):

Conv1 PROC
   mov edx, DWORD PTR _aStr$[esp-4]
   mov cl, BYTE PTR [edx]
   xor eax, eax
   test cl, cl
   je SHORT $LN1 at Conv1
   npad 4
$LL2 at Conv1:
   movsx ecx, cl
   lea eax, DWORD PTR [eax+eax*4]
   add edx, 1
   lea eax, DWORD PTR [ecx+eax*2-48]
   mov cl, BYTE PTR [edx]
   test cl, cl
   jne SHORT $LL2 at Conv1
$LN1 at Conv1:
   ret 0
Conv1 ENDP

Conv2 PROC
    sub esp, 12
    mov edx, DWORD PTR _aStr$[esp+8]
    mov cl, BYTE PTR [edx]
    xor eax, eax
    test    cl, cl
    push    esi
    mov DWORD PTR _CoefArray$[esp+16], 100
    mov DWORD PTR _CoefArray$[esp+20], 10
    mov DWORD PTR _CoefArray$[esp+24], 1
    lea esi, DWORD PTR _CoefArray$[esp+16]
    je  SHORT $LN4 at Conv2
    push    edi
    npad    3
$LL5 at Conv2:
    movsx   ecx, cl
    sub ecx, 48
    test    ecx, ecx
    jle SHORT $LN3 at Conv2
    mov edi, DWORD PTR [esi]
    imul    edi, ecx
    add eax, edi
$LN3 at Conv2:
    mov cl, BYTE PTR [edx+1]
    add edx, 1
    add esi, 4
    test    cl, cl
    jne SHORT $LL5 at Conv2
    pop edi
$LN4 at Conv2:
    pop esi
    add esp, 12
    ret 0
Conv2 ENDP

Conv3 PROC
    mov edx, DWORD PTR _aStr$[esp-4]
    movsx   eax, BYTE PTR [edx]
    sub eax, 48
    xor ecx, ecx
    test    eax, eax
    jle SHORT $LN6 at Conv3
    imul    eax, 100
    mov ecx, eax
$LN6 at Conv3:
    movsx   eax, BYTE PTR [edx+1]
    sub eax, 48
    test    eax, eax
    jle SHORT $LN3 at Conv3
    lea eax, DWORD PTR [eax+eax*4]
    lea ecx, DWORD PTR [ecx+eax*2]
$LN3 at Conv3:
    movsx   edx, BYTE PTR [edx+2]
    lea eax, DWORD PTR [edx+ecx-48]
    ret 0
Conv3 ENDP

Hat, ugy tunik a fordito szerint is az elso az egyszerubb megoldas 
(legalabbis utasitasok szama szerint). Az optimalizacot szido urak resze 
ajanlom ezt a kis csemeget:

lea eax, DWORD PTR [eax+eax*4]
...
lea eax, DWORD PTR [ecx+eax*2-48]

Itt ugye eax = (eax+eax*4)*2+eax-'a', azaz eax = eax<<3+eax<<1+ecx-'a'

Es a harmadik megoldas is tartogat nemi erdekesseget: sehol sincs benne 
ciklus! A fordito rajott, hogy az elso ciklus vegulis 100-al szoroz, ezert 
helyettesitette egy imul-al, a masodik pedig 10-el, es ott az elobb emlitett 
'lea' trukkot hasznalja. Szoval az ASM osszehasonlitas nem is teljesen fair, 
hiszen a harmadik verzional a generalt kod meg csak nem is hasonlit arra, 
amit 'kezzel irnal ASM-ban'.

Persze ez PIC-en nem megy, de 'shift left' ott is van, gondolom. Meg egy 
megjegyzes:
Az elso megoldas akarhany szamjegyre mukodik, a masodik (es harmadik) 
kizarolag 3-ra. Azaz egyre vagy kettore sem. Ez lehet, hogy problemat okoz!!

Udv,
Tantos Andras




More information about the Elektro mailing list