Ponera följande inte helt ovanliga sekvens:
Kod: Markera allt
uchar i;
for (i=0; i<100; i++)
{
}
De flesta arkitekturer stödjer inte dessa kortare ordlängder nativt, vilket innebär en massa extra manipulering.
Kod: Markera allt
uchar i;
for (i=0; i<100; i++)
{
}
bit96 skrev:Väldig förvirrande är ju att a == b[a].
Det brukar sätta griller i huvudet på många att man byta plats på fältets namn och indexet.
Hur kan indexet plötslig bli ett fält, och hur kan fältet, som just fattat är en pekare(minnesadress) plötsligt bli ett index?
Men a beräknas som *(a+b), d.v.s. "adressen a + offset b, och hämta värdet på den nya beräknade adressen"
Efter som det är en addition spelar det ju ingen roll om vi kastar om a och b, *(b+a) blir samma sak.
Men det rekommendera inte att göra så vid "normal" programmering.
Kod: Markera allt
int *talp:
...
talp+=3; /* Pekaren räknas upp med 3 POSITIONER t.ex. 3x2=6 bytes, om int är 2 bytes */
...
MiaM skrev:bit96 skrev:Väldig förvirrande är ju att a == b[a].
Det brukar sätta griller i huvudet på många att man byta plats på fältets namn och indexet.
Hur kan indexet plötslig bli ett fält, och hur kan fältet, som just fattat är en pekare(minnesadress) plötsligt bli ett index?
Men a beräknas som *(a+b), d.v.s. "adressen a + offset b, och hämta värdet på den nya beräknade adressen"
Efter som det är en addition spelar det ju ingen roll om vi kastar om a och b, *(b+a) blir samma sak.
Men det rekommendera inte att göra så vid "normal" programmering.
Men det där funkar väl bara med vissa datatyper?
Om a är en array med 32-bitarstal så kommer b multipliceras med 4 innan den läggs på pekaren a[0].
Man lär ju få cast'a en del för att över huvud taget få b[a] genom kompilatorn om variablerna är deklarerade så att a går igenom kompilatorn.
(Detta förutsatt att man inte använder nån kompilator från 1983 eller så som inte ens stödjer första versionen av ANSI-C...)
Kod: Markera allt
int *p = (int*)1000000;
p++; // ökar adressen p pekar på med sizeof(p), alltså till 1000004, INTE till 1000001 (om en int är 4bytes)
Kod: Markera allt
long tabell[10]; /* Fält med 10 st long, (long är 4 bytes i detta exempel) */
int i; /* skall användas som index i fältet (int är 2 bytes i detta exempel) */
long a, b;
i=5; /* Jag skall plocka ut värdet på position 5 i fältet så jag sätter index i till 5 */
a=tabell[i]; /* Detta fattar alla att man plockar ut en long på plats 5 i fältet, alltså värdet på position 5 plockas fram */
b=i[tabell]; /* Vissa C-programmerare fattar inget, hur f-n kan i bli en tabell och hur kan ett fält bli index ??? Jag går nog över till Pascal */
Kod: Markera allt
a=*(tabell + 5); /* Jaha, pekaren 'tabell' som pekar på long skall skall ökas med 5 POSITIONER (5*4 bytes), och hämta sen värdet där */
b=*(5 + tabell); /* Jaha, pekaren 'tabell' som pekar på long skall skall ökas med 5 POSITIONER (5*4 bytes), och hämta sen värdet där */
Kod: Markera allt
00DC L$2:
A41D0018 00DC LDQ R0, 24(FP)
2E400000 00E0 LDQ_U R18, I ; R18, (R0)
4A4000C0 00E4 EXTBL R18, R0, R0
400C99A0 00E8 CMPLT R0, 100, R0
2FFE0000 00EC UNOP
E4000009 00F0 BEQ R0, L$4
A43D0018 00F4 LDQ R1, 24(FP)
2E010000 00F8 LDQ_U R16, I ; R16, (R1)
4A0100D1 00FC EXTBL R16, I, R17 ; R16, R1, R17
4A010050 0100 MSKBL R16, I, R16 ; R16, R1, R16
42203411 0104 ADDQ R17, 1, R17
4A210171 0108 INSBL R17, I, R17 ; R17, R1, R17
46110410 010C BIS R16, R17, R16
3E010000 0110 STQ_U R16, I ; R16, (R1)
C3FFFFF1 0114 BR L$2 ; 001612
0118 L$4: ; 001613
Kod: Markera allt
00D4 L$2:
A63D0018 00D4 LDQ R17, 24(FP)
A2310000 00D8 LDL R17, I ; R17, (R17)
422C93B1 00DC CMPULT R17, 100, R17
E6200006 00E0 BEQ R17, L$4
A41D0018 00E4 LDQ R0, 24(FP)
A0000000 00E8 LDL R0, I ; R0, (R0)
40003000 00EC ADDL R0, 1, R0
A43D0018 00F0 LDQ R1, 24(FP)
B0010000 00F4 STL R0, I ; R0, (R1)
C3FFFFF6 00F8 BR L$2 ; 001612
00FC L$4: ; 001613
Kod: Markera allt
Instruction Description Byte(c, i) == 0 Nonzero Byte(c, i)
extbl Extract Byte Low i != 0 Byte(a, bl)
mskbl Mask Byte Low i == bl Byte(a, i)
insbl Insert Byte Low i != bl Byte(a, 0)
extqh Extract Quad Word High bl!=0 && i+bl<8 Byte(a, (i+bl8)&0x7)
Kod: Markera allt
struct stru {
unsigned char x;
unsigned long y;
};
struct stru s;
unsigned long i;
void main()
{
for (i=0; i<100; i++)
{
s.x = i;
s.y = i;
}
}
Kod: Markera allt
$ cc /list /machin_code /nooptimize stru
$ link /map /full stru
Kod: Markera allt
...
1 11 for (i=0; i<100; i++)
2 12 {
2 13 s.x = i;
2 14 s.y = i;
1 15 }
...
A41D0020 00E4 LDQ R0, 32(FP) ; 000013
A0000000 00E8 LDL R0, I ; R0, (R0)
A43D0018 00EC LDQ R1, 24(FP)
A2010000 00F0 LDL R16, S ; R16, (R1)
4A003610 00F4 ZAP R16, 1, R16
441FF000 00F8 AND R0, 255, R0
46000410 00FC BIS R16, R0, R16
B2010000 0100 STL R16, S ; R16, (R1)
A63D0020 0104 LDQ R17, 32(FP) ; 000014
A2310000 0108 LDL R17, I ; R17, (R17)
A65D0018 010C LDQ R18, 24(FP)
B2320004 0110 STL R17, 4(R18)
Kod: Markera allt
$ cc /list /machin_code /nooptimize /nomember_align stru.c
$ link /map /full stru
Kod: Markera allt
A65D0020 0104 LDQ R18, 32(FP) ; 000014
A2520000 0108 LDL R18, I ; R18, (R18)
A41D0018 010C LDQ R0, 24(FP)
20000001 0110 LDA R0, 1(R0)
2E000003 0114 LDQ_U R16, 3(R0)
2C200000 0118 LDQ_U R1, (R0)
4A400CF3 011C INSLH R18, R0, R19
4A400571 0120 INSLL R18, R0, R17
4A000C50 0124 MSKLH R16, R0, R16
48200441 0128 MSKLL R1, R0, R1
46130410 012C BIS R16, R19, R16
44310401 0130 BIS R1, R17, R1
3E000003 0134 STQ_U R16, 3(R0)
3C200000 0138 STQ_U R1, (R0)
Jag jobbade med flera Motorolas mikrokontroller för många år sen och de var baserade på bl.a. 68000-kärnor och högre.MiaM skrev:Det här är dock sånt som skiljer avsevärt mellan olika arkitekturer.
68000 har instruktionsuppsättning för att hantera 8, 16 och 32 bitar. De som har 16 bitars bredd på den externa bussen (68000, 68010) kräver att allt bredare än en byte är alignat på jämna 16 bitar, och alla kompilatorer jag stött på gör den aligningen default. De 68000-kretsar som har 32-bitarsbuss (68020 och högre) klarar vilken aligning/misaligning som helst, men man får en prestandaförlust för sådant som ligger fel. (68008 med åttabitarsbuss klarar nog vad jag minns också valfri aligning).
Det här gör att det blir ingen prestandaförlust att ha mindre datatyper, och på maskinerna med 16-bitarsbuss så vinner man till och med prestanda på att ha short (16-bit) istället för int (32-bit) till variabler som lagras i minnet.
(Nu har jag utgått från vad som är standard på AmigaOS, det finns säkert andra 68000-arkitekturer som brukar ha short, int och long definerat på annat sätt).