Konverzió!!!!
Erdos Zoltan
silverst at axelero.hu
Tue Sep 27 19:41:23 CEST 2005
Koszi!
Tetszik, hogy megcsinaltad... de valoban ez csak a pc-n optimalizalodik
igy...
Valszeg egy Atmelen (8051, avr) azert maskepp fordulna...
Mondjuk egy olyan procin, amin nics hw 16 bit szorzo, vagy meg esetleg
16 bit osszeado sem...
Ott aztan lehetne a foutasidot is jol tesztelni..
Szoval 8 bitesben azert fordito-szkeptikus vagyok...
Az is igaz, hogy leginkabb assemblerben programozok... egyszeruen
tisztabb helyzetet teremt, jobban kezben van.. kimarad a 'fordito mier
is szivat' jellegu debug..:-)
Z.
Andras Tantos wrote:
>> 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
>
> -----------------------------------
> Szponzorunk: http://tonerbolt.hu/
>
>
More information about the Elektro
mailing list