-
31. Data: 2014-04-05 16:19:03
Temat: Odp: C vs. ASM na przykładzie PIC18F
Od: Sylwester Łazar <i...@a...pl>
> A jakie to funkcje ta centralka miała? Niegdyś wystrugałem prostą
> centralkę na 89C52, 1 linia zew, 4 wew, LCD znakowy do monitorowania
> stanu, własny generator dzwonienia i dekoder DTMF. O ile pamiętam kod
> miał jakieś 3kB, oczywiście pisany w asm.
Na pokładzie to samo, tylko 3 linie wewnętrzne.
Funkcji jednak bardzo dużo, jak budzenie, zamawianie rozmów, blokowanie
kierunków,
, zliczanie czasu, taryfikację, itp.
To było 18 lat temu...
O właśnie, widzę, że moja żona nawet tam dodała swoje procedury :-)
char getTariff(char *wcStr1)
{
/*funkcja napisana przez xxx*/
char str2[6] = "xxxxx\0";
int j, k, p, max;
for (j=0; j<5; ++j)
{ str2[j] =48+ *( wcStr1+j);
}
max = 0;
for (k=0; k<nmax; k++)
{
j = 0;
while (str2[j] == tab[k].num[j]){
j++;
}
if (j > max)
{
max = j;
p = k;
}
}
if ((tab[p].num[max] == 'x') || (max==6))
return (tab[p].tar);
else return NOTARIFF;
}
S.
-
32. Data: 2014-04-05 17:54:15
Temat: Re: C vs. ASM na przykładzie PIC18F
Od: janusz_k <J...@o...pl>
>
> 4. AVR-GCC na atmega32 -O2 (nie znam jeszcze dokładnie avr-gcc i jego
> opcji)
> 376 ROM, 37 RAM
> bez funkcji zlicz() 222 ROM, 37 RAM
Avr studio4 zlicz() - 132 bajty
całość 356 bajtów.
--
Pozdr
Janusz
-
33. Data: 2014-04-05 18:04:57
Temat: Re: C vs. ASM na przykładzie PIC18F
Od: jacek pozniak <j...@f...pl>
janusz_k wrote:
>
>>
>> 4. AVR-GCC na atmega32 -O2 (nie znam jeszcze dokładnie avr-gcc i jego
>> opcji)
>> 376 ROM, 37 RAM
>> bez funkcji zlicz() 222 ROM, 37 RAM
> Avr studio4 zlicz() - 132 bajty
> całość 356 bajtów.
No być może, jakieś opcje trzeba ustawić, ja to kompilowałem z command line,
to są moje pierwsze wprawki w avr-gcc
jp
>
-
34. Data: 2014-04-05 18:12:52
Temat: Odp: C vs. ASM na przykładzie PIC18F
Od: Sylwester Łazar <i...@a...pl>
>Avr studio4 zlicz() - 132 bajty
>całość 356 bajtów.
Możesz wkleić kod po kompilacji?
W ATMEGA są zdaje się instrukcje 16-bitowe.
W takim razie oznacza to, że jest <66 instrukcji?
S.
-
35. Data: 2014-04-05 21:07:38
Temat: Re: Odp: C vs. ASM na przykładzie PIC18F
Od: janusz_k <J...@o...pl>
W dniu 05.04.2014 o 18:12 Sylwester Łazar <i...@a...pl> pisze:
>
>> Avr studio4 zlicz() - 132 bajty
>> całość 356 bajtów.
>
> Możesz wkleić kod po kompilacji?
Ok, poniżej.
> W ATMEGA są zdaje się instrukcje 16-bitowe.
tak
> W takim razie oznacza to, że jest <66 instrukcji?
65
Kod:
sort.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000166 00000000 00000000 00000094 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000002 00800060 00000166 000001fa 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000023 00800062 00800062 000001fc 2**0
ALLOC
3 .debug_aranges 00000020 00000000 00000000 000001fc 2**0
CONTENTS, READONLY, DEBUGGING
4 .debug_pubnames 00000067 00000000 00000000 0000021c 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_info 00000116 00000000 00000000 00000283 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_abbrev 000000ab 00000000 00000000 00000399 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_line 00000145 00000000 00000000 00000444 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_frame 00000030 00000000 00000000 0000058c 2**2
CONTENTS, READONLY, DEBUGGING
9 .debug_str 0000005e 00000000 00000000 000005bc 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 2a 00 jmp 0x54 ; 0x54 <__ctors_end>
4: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
8: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
10: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
14: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
18: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
1c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
20: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
24: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
28: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
2c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
30: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
34: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
38: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
3c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
40: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
44: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
48: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
4c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
50: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt>
00000054 <__ctors_end>:
54: 11 24 eor r1, r1
56: 1f be out 0x3f, r1 ; 63
58: cf e5 ldi r28, 0x5F ; 95
5a: d8 e0 ldi r29, 0x08 ; 8
5c: de bf out 0x3e, r29 ; 62
5e: cd bf out 0x3d, r28 ; 61
00000060 <__do_copy_data>:
60: 10 e0 ldi r17, 0x00 ; 0
62: a0 e6 ldi r26, 0x60 ; 96
64: b0 e0 ldi r27, 0x00 ; 0
66: e6 e6 ldi r30, 0x66 ; 102
68: f1 e0 ldi r31, 0x01 ; 1
6a: 02 c0 rjmp .+4 ; 0x70 <.do_copy_data_start>
0000006c <.do_copy_data_loop>:
6c: 05 90 lpm r0, Z+
6e: 0d 92 st X+, r0
00000070 <.do_copy_data_start>:
70: a2 36 cpi r26, 0x62 ; 98
72: b1 07 cpc r27, r17
74: d9 f7 brne .-10 ; 0x6c <.do_copy_data_loop>
00000076 <__do_clear_bss>:
76: 10 e0 ldi r17, 0x00 ; 0
78: a2 e6 ldi r26, 0x62 ; 98
7a: b0 e0 ldi r27, 0x00 ; 0
7c: 01 c0 rjmp .+2 ; 0x80 <.do_clear_bss_start>
0000007e <.do_clear_bss_loop>:
7e: 1d 92 st X+, r1
00000080 <.do_clear_bss_start>:
80: a5 38 cpi r26, 0x85 ; 133
82: b1 07 cpc r27, r17
84: e1 f7 brne .-8 ; 0x7e <.do_clear_bss_loop>
86: 0e 94 8b 00 call 0x116 ; 0x116 <main>
8a: 0c 94 b1 00 jmp 0x162 ; 0x162 <_exit>
0000008e <__bad_interrupt>:
8e: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000092 <zlicz>:
ADRDIOD[4][0]=2;
ADRDIOD[4][1]=1;
zlicz();
}
void zlicz(){
92: e0 e8 ldi r30, 0x80 ; 128
94: f0 e0 ldi r31, 0x00 ; 0
char i; // zmienna pomocnicza
char j; // zmienna pomocnicza
for(i = 0 ; i < k ; ++i)
LICZV[i] = 0; // zerowanie tablicy
96: 11 92 st Z+, r1
void zlicz(){
char i; // zmienna pomocnicza
char j; // zmienna pomocnicza
for(i = 0 ; i < k ; ++i)
98: 80 e0 ldi r24, 0x00 ; 0
9a: e7 38 cpi r30, 0x87 ; 135
9c: f8 07 cpc r31, r24
9e: d9 f7 brne .-10 ; 0x96 <zlicz+0x4>
a0: a2 e6 ldi r26, 0x62 ; 98
a2: b0 e0 ldi r27, 0x00 ; 0
LICZV[i] = 0; // zerowanie tablicy
for(i = 0 ; i < n ; ++i)
++LICZV[VDIOD[i]]; // po tych operacjach LICZV[i] będzie
zawierała
a4: ed 91 ld r30, X+
a6: f0 e0 ldi r31, 0x00 ; 0
a8: e0 58 subi r30, 0x80 ; 128
aa: ff 4f sbci r31, 0xFF ; 255
ac: 80 81 ld r24, Z
ae: 8f 5f subi r24, 0xFF ; 255
b0: 80 83 st Z, r24
char j; // zmienna pomocnicza
for(i = 0 ; i < k ; ++i)
LICZV[i] = 0; // zerowanie tablicy
for(i = 0 ; i < n ; ++i)
b2: 80 e0 ldi r24, 0x00 ; 0
b4: a7 36 cpi r26, 0x67 ; 103
b6: b8 07 cpc r27, r24
b8: a9 f7 brne .-22 ; 0xa4 <zlicz+0x12>
ba: e0 e8 ldi r30, 0x80 ; 128
bc: f0 e0 ldi r31, 0x00 ; 0
++LICZV[VDIOD[i]]; // po tych operacjach LICZV[i] będzie
zawierała
// liczbę wystąpień elementów o kluczu i
for(i = 1 ; i < k ; ++i)
LICZV[i] += LICZV[i-1]; // teraz LICZV[i] zawiera pozycje w
posortowanej
be: 81 81 ldd r24, Z+1 ; 0x01
c0: 90 81 ld r25, Z
c2: 89 0f add r24, r25
c4: 81 83 std Z+1, r24 ; 0x01
c6: 31 96 adiw r30, 0x01 ; 1
LICZV[i] = 0; // zerowanie tablicy
for(i = 0 ; i < n ; ++i)
++LICZV[VDIOD[i]]; // po tych operacjach LICZV[i] będzie
zawierała
// liczbę wystąpień elementów o kluczu i
for(i = 1 ; i < k ; ++i)
c8: a0 e0 ldi r26, 0x00 ; 0
ca: e6 38 cpi r30, 0x86 ; 134
cc: fa 07 cpc r31, r26
ce: b9 f7 brne .-18 ; 0xbe <zlicz+0x2c>
d0: 34 e0 ldi r19, 0x04 ; 4
LICZV[i] += LICZV[i-1]; // teraz LICZV[i] zawiera pozycje w
posortowanej
// tablicy ostatniego elementu o kluczu i
for(i = n-1 ; i >= 0 ; --i)
{
j=--LICZV[VDIOD[i]]; // aktualizacja LICZV
d2: 83 2f mov r24, r19
d4: 90 e0 ldi r25, 0x00 ; 0
d6: fc 01 movw r30, r24
d8: ee 59 subi r30, 0x9E ; 158
da: ff 4f sbci r31, 0xFF ; 255
dc: 20 81 ld r18, Z
de: a2 2f mov r26, r18
e0: b0 e0 ldi r27, 0x00 ; 0
e2: a0 58 subi r26, 0x80 ; 128
e4: bf 4f sbci r27, 0xFF ; 255
e6: ec 91 ld r30, X
e8: e1 50 subi r30, 0x01 ; 1
ea: ec 93 st X, r30
VDOUT[j] = VDIOD[i]; //wstawienie elementu na odpowiednią pozycję
ec: f0 e0 ldi r31, 0x00 ; 0
ee: df 01 movw r26, r30
f0: a5 58 subi r26, 0x85 ; 133
f2: bf 4f sbci r27, 0xFF ; 255
f4: 2c 93 st X, r18
ADRDOUT[j][0] = ADRDIOD[i][0]; // sortowanie adresów
f6: ee 0f add r30, r30
f8: ff 1f adc r31, r31
fa: e9 59 subi r30, 0x99 ; 153
fc: ff 4f sbci r31, 0xFF ; 255
fe: 88 0f add r24, r24
100: 99 1f adc r25, r25
102: 8f 58 subi r24, 0x8F ; 143
104: 9f 4f sbci r25, 0xFF ; 255
106: dc 01 movw r26, r24
108: 2c 91 ld r18, X
10a: 20 83 st Z, r18
ADRDOUT[j][1] = ADRDIOD[i][1]; // sortowanie adresów
10c: 11 96 adiw r26, 0x01 ; 1
10e: 8c 91 ld r24, X
110: 81 83 std Z+1, r24 ; 0x01
++LICZV[VDIOD[i]]; // po tych operacjach LICZV[i] będzie
zawierała
// liczbę wystąpień elementów o kluczu i
for(i = 1 ; i < k ; ++i)
LICZV[i] += LICZV[i-1]; // teraz LICZV[i] zawiera pozycje w
posortowanej
// tablicy ostatniego elementu o kluczu i
for(i = n-1 ; i >= 0 ; --i)
112: 31 50 subi r19, 0x01 ; 1
114: de cf rjmp .-68 ; 0xd2 <zlicz+0x40>
00000116 <main>:
char ADRDIOD[5][2];//tablica adresów diod
char ADRDOUT[5][2];//tablica adresów diod po posegregowaniu
char LICZV[5]; // zawiera liczbę elementów o danej wartości
void main (void){
VDIOD[0]=1;
116: 91 e0 ldi r25, 0x01 ; 1
118: 90 93 62 00 sts 0x0062, r25
VDIOD[1]=2;
11c: 22 e0 ldi r18, 0x02 ; 2
11e: 20 93 63 00 sts 0x0063, r18
VDIOD[2]=6;
122: 86 e0 ldi r24, 0x06 ; 6
124: 80 93 64 00 sts 0x0064, r24
VDIOD[3]=4;
128: 84 e0 ldi r24, 0x04 ; 4
12a: 80 93 65 00 sts 0x0065, r24
VDIOD[4]=3;
12e: 83 e0 ldi r24, 0x03 ; 3
130: 80 93 66 00 sts 0x0066, r24
ADRDIOD[0][0]=1;
134: 90 93 71 00 sts 0x0071, r25
ADRDIOD[0][1]=0;
138: 10 92 72 00 sts 0x0072, r1
ADRDIOD[1][0]=1;
13c: 90 93 73 00 sts 0x0073, r25
ADRDIOD[1][1]=1;
140: 90 93 74 00 sts 0x0074, r25
ADRDIOD[2][0]=1;
144: 90 93 75 00 sts 0x0075, r25
ADRDIOD[2][1]=2;
148: 20 93 76 00 sts 0x0076, r18
ADRDIOD[3][0]=2;
14c: 20 93 77 00 sts 0x0077, r18
ADRDIOD[3][1]=0;
150: 10 92 78 00 sts 0x0078, r1
ADRDIOD[4][0]=2;
154: 20 93 79 00 sts 0x0079, r18
ADRDIOD[4][1]=1;
158: 90 93 7a 00 sts 0x007A, r25
zlicz();
15c: 0e 94 49 00 call 0x92 ; 0x92 <zlicz>
}
160: 08 95 ret
00000162 <_exit>:
162: f8 94 cli
00000164 <__stop_program>:
164: ff cf rjmp .-2 ; 0x164 <__stop_program>
--
Pozdr
Janusz
-
36. Data: 2014-04-05 23:19:19
Temat: Odp: Odp: C vs. ASM na przykładzie PIC18F
Od: Sylwester Łazar <i...@a...pl>
>> W ATMEGA są zdaje się instrukcje 16-bitowe.
>tak
>> W takim razie oznacza to, że jest <66 instrukcji?
>65
Dzięki. Dobra robota.
Podoba mi się ten ATMEGA32 (jak na 8-bitowca)
Ma fajne instrukcje:
1) MOVW Rd, Rr Copy Register Word Rd+1:Rd <- Rr+1:Rr
w jednym cyklu!
3x jej używają w naszym programie testowym. Nie dziwię się. Tego brakuje w
PIC.
2) LDI Rd, K Load Immediate Rd <- K
14x jej używają
Też w jednym cyklu do dowolnego rejestru. Tez brakuje w PICu. Wszystko przez
WREG trzeba przenosić.
3)CPI Rd,K Compare Register with Immediate Rd - K
3x użyta
Też w jednym cyklu. Też brakuje w PICu.
4) CPC Rd,Rr Compare with Carry Rd - Rr - C
3x użyta.
Też występuje w jednym cyklu.
Zdaje się, że tak fajnie można porównać w 4 instrukcjach 2bajtową liczbę.
ldi r26, 0x00 ; 0
cpi r30, 0x86 ; 134
cpc r31, r26
brne .-18 ; 0xbe <zlicz+0x2c>
Szkoda tylko, że nie ma takiego porównania cpc ze stałą i tutaj musiał
załadować najpierw do r26 zero.
W PIC18 jest CPFSEQ, która ze skokiem wykonuje się w 3 cyklach, ale też
trzeba załadować do w stałą
i też tylko jeden bajt, a nie słowo. Ach te ośmiobitowce :-(
5)MOV Rd, Rr Move Between Registers Rd <- Rr
5x występuje
Też w jednej instrukcji i też fajne.
PIC18 ma MOVFF, ale trwa 2 cykle, czyli identycznie, jak w PIC16
MOVF R1,w
MOVWF R2
tyle, że nie używa w.
----------------------------------
Podsumowując:
1) Kod wygląda dość ciekawie, ale coś mi się zdaje, że można to jeszcze
skrócić przynajmniej do 45 instrukcji z takim zestawem rozkazów.
2) rozkazy korzystające z indeksów trwają zawsze 2 cykle
np.
LD Rd, Z Load Indirect Rd <- (Z)
3) pętla główna sortowania zajmuje aż 34 rozkazy.
8 rozkazów 2 cyklowych
26 rozkazów 1 cyklowych
czyli 26+2*8=26+16=42 cykle
4) Ja mam w ASM na PIC18F 20 instrukcji w pętli.
I tak:
6 wykonujących się w 2 cyklach
14 wykonujących się w 1 cyklu.
Co daje mimo bardziej ubogiej listy rozkazów 14+2*6=14+12=26cykli
W cyklach wychodzi C/ASM= 42/26=1,62
Całkiem nieźle jak na razie. Nawet nie dwukrotna nadbudowa.
5) ATMEGA32 może pracować, jak dobrze wyczytałem @16MHz z czasem jednego
cyklu: Tcy=1/16=62,5ns.
Daje to obieg pętli:
42*62,5=2,625us
Dla PICa 18F2320 @40MHz Tcy=1/40*4=100ns
Daje to obieg pętli:
26*100= 2,6us
I to jest ciekawa sprawa.
==================================================
ATMEGA32 z kompilatorem C (nie wiem jaka wersja?) Avr studio4
Wykonuje tą samą funkcję, którą napisałem w ASM na PIC18 mniej więcej w tym
samym czasie!
Sukces polega zapewne na tym, że ATMEGA32 wydaje się dość zgrabnym
maleństwem,
a kompilator korzysta z listy rozkazów dość logicznie.
Oba procki mają tylko 3 rejestry indeksowe. Jeden więcej byłby w tym
przypadku pomocny.
ATMEGA32 jakieś 12-15 zł
PIC18F2320 jakieś 20 -28 zł
Polecam ATMEGA32 w takim razie, zarówno do pracy w ASM jak i w C.
Choć zaznaczam, że na ATMEGA32 kawałka kodu jeszcze nie napisałem w ASM :-)
Jednak, 8-bitowce to marne są,
więc jeśli już lepiej to takiego 32MX220F032B-50ISP za 8 zł.
==================================================
Uwaga:
Co prawda jeszcze nie mówiłem, że ten mój kod w ASM vs. C ma automatyczne
odliczanie najmniejszej wartości KMIN,
w celu zmniejszenia rozmiaru tablicy zliczającej.
Ale to myślę, że jakieś 5-15% szybkości może zabrać w ASM.
Bardzo dziękuję Janusz.
Podaj proszę jeszcze typ kompilatora, wersję i może jakiegoś linka do tego
AVRSTUDIO i kompilatora (demo?)
Może się komuś przyda.
S.
-
37. Data: 2014-04-06 00:32:54
Temat: Re: C vs. ASM na przykładzie PIC18F
Od: Mario <m...@...pl>
W dniu 2014-04-05 23:19, Sylwester Łazar pisze:
> ATMEGA32 jakieś 12-15 zł
> PIC18F2320 jakieś 20 -28 zł
> Polecam ATMEGA32 w takim razie, zarówno do pracy w ASM jak i w C.
Ja bym go nie polecał bo ten procek znika z rynku. Jeśli już to jakiś
zamiennik np Atmega328. A tak w ogóle po co kupować 8 bitowy procek z
1kB RAM za 12-15 zł gdy można kupić 32 bitowy z 8kB RAM za 7 zł?
http://www.tme.eu/pl/details/lpc1114fbd48_302/mikrok
ontrolery-nxp-arm/nxp/#
--
pozdrawiam
MD
-
38. Data: 2014-04-06 00:36:48
Temat: Re: C vs. ASM na przykładzie PIC18F
Od: Marek <f...@f...com>
On Sat, 05 Apr 2014 11:10:32 +0200, jacek pozniak
<j...@f...pl> wrote:
> 3. Kompilator XC8, ver 1.3 --opt=ALL (60-dniowa) procesor
pic18f252: nie
C18: samo zlicz() bez prologu, epilogu i bez extended 171 słów, z
extended 157 słów.
--
Marek
-
39. Data: 2014-04-06 00:43:36
Temat: Odp: C vs. ASM na przykładzie PIC18F
Od: Sylwester Łazar <i...@a...pl>
> On Sat, 05 Apr 2014 11:10:32 +0200, jacek pozniak
> <j...@f...pl> wrote:
> > 3. Kompilator XC8, ver 1.3 --opt=ALL (60-dniowa) procesor
> pic18f252: nie
>
> C18: samo zlicz() bez prologu, epilogu i bez extended 171 słów, z
> extended 157 słów.
>
> --
> Marek
Dzięki.
Chyba jeden z gorszych wyników :-(
S.
-
40. Data: 2014-04-06 00:47:48
Temat: Odp: C vs. ASM na przykładzie PIC18F
Od: Sylwester Łazar <i...@a...pl>
> > ATMEGA32 jakieś 12-15 zł
> > PIC18F2320 jakieś 20 -28 zł
> > Polecam ATMEGA32 w takim razie, zarówno do pracy w ASM jak i w C.
>
> Ja bym go nie polecał bo ten procek znika z rynku. Jeśli już to jakiś
> zamiennik np Atmega328. A tak w ogóle po co kupować 8 bitowy procek z
> 1kB RAM za 12-15 zł gdy można kupić 32 bitowy z 8kB RAM za 7 zł?
>
http://www.tme.eu/pl/details/lpc1114fbd48_302/mikrok
ontrolery-nxp-arm/nxp/#
> --
> pozdrawiam
> MD
Z tych dwóch. Poniżej napisałem o 32 bitowym 32MX2xx.
O.K.
Wygląda, że 8-bitowce się kończą.
Ale zawsze mogą służyć za PORT EXPANDER.
Jeśli będzie w cenie takiej co CD4094, to można kupić takiego 8-bitowca i
jeszcze sobie,
do płytki piny dostosować :-)
S.