|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 11:10 am
| Автор |
Съобщение |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Ами зависи какво гониш. Скоростта на обработка ще е същата, но ще заема по-малко памет.
|
| Чет Яну 05, 2006 8:47 pm |
|
 |
|
Balkana
Ранг: Популярен
Регистриран на: Чет Дек 01, 2005 10:42 pm Мнения: 301
|
Според мен като количество инструкции е същото (аз работя главно в thumb) и като последователност от инструкции за обработка на байт или 32-битова дума се образува последователност с еднаква дължина. Друг е въпроса колко памет ти заема променливата. Понякога нямаш никаква печалба от това да използваш char вместо int, ако е необходимо подравняване на следващите данни.
например:
char p;
char *t;
заема същото количество памет, като
int p;
char *t;
поради факта, че указателя е 32-битов, и трябва да бъде заделена памет на адрес кратен на 4.
Арм-а на Micronas който ползвам например не умее да прави неподравнен достъп до памет. Т.е достъп до байт може да е на произволен адрес; достъп до 16-битова променлива е задължително на четен адрес; 32-битова дума трябва да е на адрес кратен на 4. Иначе се получава некоректен достъп. В точно този процесор Data Abort handler-а не работи (защо - за мене е тайна, така казаха от Micronas), но в Atmel-ските и STR работи. Не съм изследвал дали могат да правят неподравнен достъп, но нормално ако не може, тогава се получава Data Abort.
Това е различно за различните процесори, и не е задължително правило при използване на външна шина - зависи изцяло от това какво е направил производителя.
|
| Чет Яну 05, 2006 9:50 pm |
|
 |
|
bateAz
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 4:11 pm Мнения: 3750 Местоположение: София
|
При MSP430 и IAR EW обявяването на променлива от тип CHAR пести място в RAM-a, защото процесорът умее да адресира байт на нечетен адрес ( но дума не ще ). Ако обявя много CHAR-ове, независимо в какъв ред и как ги мешам с по-дълги променливи, линкерът ги поставя първо байтовите, след това другите.
Така че, там има смисъл да се ограничаваш да байт. Има обаче и ядра, където това е безсмислено - напр. MC56F.... Не печелиш памет, дори губиш скорост.
|
| Чет Яну 05, 2006 10:44 pm |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
ако разглеш една схема на свързване ЦПУ-РАМ ще ти стане ясно как става, най общо 16/32 битовия РАМ позволява 8 битов достъп чрез допълнителни управляващи сигнали.
|
| Чет Яну 05, 2006 11:15 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Първо на въпроса на Никола.
Обяви тази променлива като unsigned char без никакви угризения.
Балканджията го каза точно като инструкции е същото има значение единственно там където трябва да се подравняват данните. Но примера който е дал е относителен.
Добре:
char Var;
char* pVar;
заема същото място като
int Var;
int* pVar;
Но
char Var1;
char Var2;
char Var3;
char Var4;
char* pVar1;
дали ще заема същото място като
int Var1;
int Var2;
int Var3;
int Var4;
int * pVar1;
Имайте в предвид че за процесорите за които говорим int е 32 бита.
Тоест който дава съвет от сорта на: "За предпочитане е данните да се обявяват като int вместо char." Трябва да поясни за какъв процесор става въпрос и за колко променливи и... и....
На въпроса на Цецо. За да имаш достъп до 8, 16 и 32 бита с една инструкция при 32 битова външна шина трябва да имаш към шината и сигнали BLS(ByteLaneSelect). При LPC2000 ги има.
И още:
ARM7 асемблера има следните инструкции:
LDR и STR - адресират 32 битови данни;
LDRH и STRH - адресират 16 битови данни;
LDRB и STRB - адресират 8 битови данни;
Balkana какво имаш впредвид под Abort Data handler-а не работи. Handler-а си го пишеш ти или ползваш готов към компилатора. Може би имаш впредвид, че ядрото не влиза в "exeption" когато програмата прави непозволен достъп?
|
| Чет Яну 05, 2006 11:21 pm |
|
 |
|
ДедоБоре
Ранг: Форумен бог
Регистриран на: Нед Ное 21, 2004 11:31 pm Мнения: 10088
|
абе дори и процесора да може да вземе неподравнени данни, било с бъс-трап или не, му трябват поне 2 цикъла. в някои специфични инструкции r-m-w, стрингови или блиндови операнди, може да не работи изобщо. говоря по принцип, не само за АРМ ядра. ефекта от това е, че една и съща компилирана програма върви по-бавно на 64-ботов процесор отколкото на 32. затова, нещата, които са критични, задължително се пишат с голямо внмание и много обяснения на компилатора, за да може той да ги нагласи при свързването.
ако става въпрос за данни, особено структури, трябва да внимаваш когато ги мешеш с по-големи типове, последните да не станат неподравнени.
например:
struct {
char a,b,c;
int i
}
'i' става неподравнено, ако приемем, че 'а' е подравнено. как се прави 'а' подравнено зависи от компилатора.
затова е по-добре да напишеш:
struct{
int i;
char a,b,c;
}
защото, компилатора вероятно ще се усети и ще подравни 'i'
обаче ако ти трябва още една голяма:
struct{
int i;
char a,b,c;
int k;
}
'k' става неподравнено. затова трябва да си ги подрваниш сам:
struct{
int i;
char a,b,c;
char pad;
int k;
}
всичко обаче е много 'компилаторо-зависимо' и дори при един и същ компилатор за различни архитектури се получават различни резултати. дори не може да си сигурен, че 'unsigned short' е едно и също в различните архитектури - в някои може да е 8 бита, в някои 16, а за бъдещите 256-битови процесори, може и да 32 бита...  ANSI-C не дава точна дефиниция
затова е добра практика да работиш с мета-типове, в които си дефинираш нещата ясно (за тебе). после е въпрос на време да го обясниш и на компилатора...
typedef unsigned char u08;
typedef unsigned short u16;
подобни дефиниции си ги пишеш в един файл, например types.h и ако се налага да мигрираш, бъзикаш само този файл.
накрая:
всичко, което написах е много теоретично и повърхостно. има книги по 800 стр. с полезни съвети в този дух. за да си наясно какво става, трябва да гледаш компилирания резултат винаги, когато имаш някакво съмнение и да пробваш различни варианти. особено ако ползваш различни нива на оптимизация. на всичкото отгоре, купона почва наново с всяка нова версия на компилатора.
искам да кажа, че няма универална рацепта от рода 'СДС е по-дорбо от БСП'.  за разлика от политиката, обаче, компилатора ще изтрае всякакви издевателства
|
| Чет Яну 05, 2006 11:21 pm |
|
 |
|
Balkana
Ранг: Популярен
Регистриран на: Чет Дек 01, 2005 10:42 pm Мнения: 301
|
Дедо Боре го каза добре  Точно така е, най-вече е компилаторно зависимо, освен за нещата за които е ясно че няма как да не станат. А като човек включи оптимизациите, само един господ може да предрече какво ще спретне компилатора. Обичам да го проверявам по тази причина отвреме-навреме.
Zdrav:
>>Balkana какво имаш впредвид под Abort Data handler-а не работи. Handler-а си го пишеш ти или ползваш готов към компилатора. Може би имаш впредвид, че ядрото не влиза в "exeption" когато програмата прави непозволен достъп?
Ами от Micronas си признаха без бой че сигнала "abort" на АРМ ядрото в процесора е закачен твърдо вътрешно на неактивно ниво, т.е. exception по data abort ама никога и по никоя причина няма да се случи.
A и лично съм пробвал какво става с неподравнен достъп  няма exception, само данните са тотално сгрешени 
|
| Чет Яну 05, 2006 11:33 pm |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
ще си позволя да пофилосовствам малко:
за всеки уважаващ себе си компилатор char, short и long трябва да са съответно 8, 16, 32 бита, а int равен на разредността на ЦПУто. Така всеки програмист трябва да използва char, short или long ако иска да е сигурен в размерността на променливата която иска; и да използва int за променливи с които се изисква бързина (итерационни такива), например следния код ще се компилира добре за каквито и да е архитектури:
void memcpy( unsigned char *dst, unsigned char *src, int len )
{
int i;
for ( i=0; i<len; i++, dst++, src++ )
*dst = *src;
}
1) трябва да се има предвид максималните стойности на int променливите дали могат да се поемат от разредността на ЦПУто
2) CCS не е уважаващ себе си компилатор, защото при него long е 16 бита
Това е мое мнение, не е задължително да е 100% вярно, но като програмист на С, снятам че е такава идеята.
|
| Чет Яну 05, 2006 11:48 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Къв съм тъп - не се сетих, че има псевдо-процесори, които не могат да адресират отделни байтове. 
|
| Пет Яну 06, 2006 12:10 am |
|
 |
|
ДедоБоре
Ранг: Форумен бог
Регистриран на: Нед Ное 21, 2004 11:31 pm Мнения: 10088
|
тито, благодаря за примера  той много добре илюстрира съвременната неприносимост на С
според теб, unsigned short е 16 бита. а според мен е 8 бита. истината е, че според gcc-arm ще е едно, а според gcc-avr ще е друго, може би според gcc-amd64 ще е трето, не съм пробвал.
от това следва, че писането на 'unsigned short' в програмата я прави почти непреносима. моята идея е да се пише в програмата u16, и си е твоя грижа да дефинираш какво точно означава u16 в конкретния порт за конкретната аритектура. всеки, който чете кода ще схване веднага за какво иде реч, и ако трябва да се пипа, ще е само на едно място. може даже да е направено с #ifdef AVR
ще си позволя и да коментирам твоя пример:
- i e по-добре да е register unsigned int
- i е донякъде безсмислено, защото може да се използва len като регистрова. повечето процесори имат условен цикъл с декрементация на регистър, а 'i<len' е поне още едно сравнение. в този смисъл, while (len--) {} e по-ефективно от for
- какво ще стане, ако някой идиот подаде len отрицателно?
- *src и *dst може и да не са байтове, нали? ама опираме пак до подравняване 
|
| Пет Яну 06, 2006 12:18 am |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
100% съм съгласен с теб в първата част на съобщението ти
но коментарите ти няма да приема поради простата причина че кода го дадох само като пример подкрепящ тезата ми, а не като максимално оптимизирана мемкопи функция, т.е. в случая са малко като заяждане от твоя страна, но както и да е - без лоши чувства 
|
| Пет Яну 06, 2006 12:29 am |
|
 |
|
ДедоБоре
Ранг: Форумен бог
Регистриран на: Нед Ное 21, 2004 11:31 pm Мнения: 10088
|
извинявай...
идеята беше да покажа колко много влияят малките вариации, затова написах 'коментирам', а не 'критикувам'
понеже кольо имаше питане относно 'портване', трябва да е ясно, че дори тривиална функция като memcpy е трудна за универсално написване
|
| Пет Яну 06, 2006 12:47 am |
|
 |
|
Nikola Kirov
Ранг: Форумен бог
Регистриран на: Нед Окт 31, 2004 9:19 pm Мнения: 4464 Местоположение: Stara Zagora
|
Мерси. Доста изчерпателно.
За сега ми е напълно достатъчно да работя. Пък детаилно ще изучавам поведението на компилатора като се запозная с асемблера
|
| Пет Яну 06, 2006 2:00 am |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 2 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|