Hindu Code in Microchip
Понадобилось быстро подключить SD-карточку к микроконтроллеру, и задача казалась простецкой — добрый микрочип предлагает библиотеки для всего чего угодно(ах, поставить линк на библиотеки — не судьба), но после первого взгляда на их код, волосы на голове начали шевелиться.
Те кто общался с саппортом микрочипа, наверное замечал что зачастую попадает на индийский департамент конторы, и все-бы ничего если бы не подозрение что весь микрочип разом переехал в Бомбей и набрал индийских бездомных школьников для написания своих библиотек.
Do not think that I'm trying to bend a racially correct line - I didn’t have experience specifically with Indians, but I know for sure that there are enough of them among our people (don’t believe it, type “95” in Google ), but the concept of “Hindu code” appeared long ago and entrenched quite firmly, although you will not find it in the politically correct Wikipedia (but googol knows about it for sure).
So, if you want to learn how to program like this in a microchip, follow these simple tips ...
The most important thing to remember whenhiring when you get a job in a microchip is: "They still pay for lines of code!". Therefore, by any means increase the volume of source texts. The advice is general, so without examples, include fantasy.
The classic of the Hindumovie code genre has been unshakable since its inception. To warm up, try to guess what is hidden behind this piece of code contained in the file “MDD File System \ SD-SPI.c” on line 1042:
In the absence of imagination, copy-paste is also suitable, although according to rumors many employers check the code for copy-paste, the microchip is apparently not one of them. Remember, never use macros to cut the dough with the Hindu code - they evil and ugly reduce the code. For example, a piece repeating twenty times in the MDD File System \ FSIO.c file:
In general, I can not stand copy-paste in programming. If there is a desire to copy something, I immediately think about where and what to rewrite. And if there is a need for the same piece of code that cannot be wrapped in a function, then instead of blunt copying, you can make a macro out of it, which will be both more readable and easier to edit in the future:
A ratio of 10: 1 in favor of the first option, and given twenty repetitions in absolute terms, this is several hundred rupees!
Using cycles is evil. A linear program runs much faster without wasting time on condition statements and transitions, and contains more lines of code.
Initialization of structures should be byte-by-bye, no need to write simple initializers like:
The idea of the FileObjectCopy function in the file “MDD File System \ FSIO.c” on line 6065 led me to another thought, I suspect that if they had more different structures then other SomeObjectCopy would appear
Description charms with simplicity:
Well, there are still little things for inflating the code, with which you can add a couple - three lines, such as:
Even if it is solely to make the read-only variable, then such a macro is quite enough for the compiler to swear where necessary:
Comment on everything except the most unintelligible pieces (see Example 1.) If you have not yet reached full enlightenment and two or three functions have accidentally remained in your Hindu program - create a “function description template”, include smart section words in the section "Description" list again everything that was written above, but expanded. Especially the effect of multiplying lines of code is manifested with functions like “FSerror ()” from the example above.
All that has been written above is general advice for beginners on the path to enlightenment, applicable to any program, in almost any language. But real Shiva fans use every opportunity to create chaos. Given the curvature of the Harvard architecture of PIC controllers, the real gurus of the Hindu code will discover an unbelievable number of possibilities for using specific directives and other features of the curvature of the C implementation in compilers.
Write the code in such a way that it cannot even compile under different versions of compilers, and use all the specific #pragma. In this case, each function will be present in versions for at least two compilers and three to four PIC architectures, for a total of up to 8 times the code increase.
It will help you to double the amount of code once again that the RAM and ROM pointers in the compilers for PIC are different, that is, “char *” cannot be converted explicitly or implicitly to “const char *” in high tech or “const rom char *” in microchip . Which, in general, does not cause any problems at all in high-tech, since void, far and const pointers can address all memory and apply to both ROM and RAM. But in the microchip implementation of si, this can lead to the creation of two functions: one working with ROM, and the second with RAM - pure profit. You should never be content with one function that works with RAM (and, if necessary, loads constants from ROM there).
And finally, always use inline assembler even in cases when your code is much longer and slower than what the compiler does from a normal C program. Assembler looks cool and most will not suspect the poor folly that was applied when it was created, and they will also assume that the program is written as one of the best possible methods.
Trying to make the microchip miracle work (their site still rose) I spent a little more time than the one for which I wrote my implementation of working with SD and ported the file system taken here , which I warn you about - more accurately: “glitch inside”.
Те кто общался с саппортом микрочипа, наверное замечал что зачастую попадает на индийский департамент конторы, и все-бы ничего если бы не подозрение что весь микрочип разом переехал в Бомбей и набрал индийских бездомных школьников для написания своих библиотек.
Do not think that I'm trying to bend a racially correct line - I didn’t have experience specifically with Indians, but I know for sure that there are enough of them among our people (don’t believe it, type “95” in Google ), but the concept of “Hindu code” appeared long ago and entrenched quite firmly, although you will not find it in the politically correct Wikipedia (but googol knows about it for sure).
Hindu code (not Indian or Native American) is a slang common name for extremely low-quality program code that uses simple but vicious copy-paste principles.
Why Hindu?
According to rumors in India, for some time, there has been a practice of evaluating the productivity of a programmer based on the amount of code written. The more code, the more the programmer works, and therefore, his salary is higher. Nimble Indians quickly figured out how to trick unskilled customers.
Useful note from kaladhara
A resident of India is Indian, and a Hindu is a follower of any direction of Hinduism. Thus, even the Chukchi of advanced years, professing Shaivism (and probably writing in C ++) is an Indian.
So, if you want to learn how to program like this in a microchip, follow these simple tips ...
0. More code - more profit!
The most important thing to remember when
1. Classics of the genre
The classic of the Hindu
if(localCounter != 0x0000)
{
localPointer--;
while(1)
{
SPIBUF = 0xFF;
localPointer++;
if((--localCounter) == 0x0000)
{
break;
}
while(!SPISTAT_RBF);
*localPointer = (BYTE)SPIBUF;
}
while(!SPISTAT_RBF);
*localPointer = (BYTE)SPIBUF;
}
do not rush to look in the ANSWER - it's simple:
// в данном контекте (если значение счетчика на выходе не важно) сойдет и такое
while (localCounter--)
{
SPIBUF = 0xFF;
while (!SPISTAT_RBF);
*localPointer++ = SPIBUF;
}
// а это полный аналог, имеющий на выходе то же значение счетчика
// правда на одну строчку длиннее - чуть менее эффектно
while (localCounter)
{
localCounter--;
SPIBUF = 0xFF;
while (!SPISTAT_RBF);
*localPointer++ = SPIBUF;
}
2. Copy-paste
In the absence of imagination, copy-paste is also suitable, although according to rumors many employers check the code for copy-paste, the microchip is apparently not one of them. Remember, never use macros to cut the dough with the Hindu code - they evil and ugly reduce the code. For example, a piece repeating twenty times in the MDD File System \ FSIO.c file:
ctrl + v
if (utfModeFileName)
{
utf16path++;
i = *utf16path;
}
else
{
temppath++;
i = *temppath;
}
In general, I can not stand copy-paste in programming. If there is a desire to copy something, I immediately think about where and what to rewrite. And if there is a need for the same piece of code that cannot be wrapped in a function, then instead of blunt copying, you can make a macro out of it, which will be both more readable and easier to edit in the future:
simple and clear replacement for the piece above
#define getnextpathchar() ( utfModeFileName ? *++utf16path : *++temppath ) // где-то в начале
...
i = getnextpathchar(); // там где надо
A ratio of 10: 1 in favor of the first option, and given twenty repetitions in absolute terms, this is several hundred rupees!
3. Line code
Using cycles is evil. A linear program runs much faster without wasting time on condition statements and transitions, and contains more lines of code.
feel free to do so
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part3[1];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part3[0];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[5];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[4];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[3];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[2];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[1];
fileFoundString[fileFoundLfnIndex--] = lfnObject.LFN_Part2[0];
tempShift.byte.LB = lfnObject.LFN_Part1[8];
tempShift.byte.HB = lfnObject.LFN_Part1[9];
fileFoundString[fileFoundLfnIndex--] = tempShift.Val;
tempShift.byte.LB = lfnObject.LFN_Part1[6];
tempShift.byte.HB = lfnObject.LFN_Part1[7];
fileFoundString[fileFoundLfnIndex--] = tempShift.Val;
tempShift.byte.LB = lfnObject.LFN_Part1[4];
tempShift.byte.HB = lfnObject.LFN_Part1[5];
fileFoundString[fileFoundLfnIndex--] = tempShift.Val;
tempShift.byte.LB = lfnObject.LFN_Part1[2];
tempShift.byte.HB = lfnObject.LFN_Part1[3];
fileFoundString[fileFoundLfnIndex--] = tempShift.Val;
tempShift.byte.LB = lfnObject.LFN_Part1[0];
tempShift.byte.HB = lfnObject.LFN_Part1[1];
fileFoundString[fileFoundLfnIndex--] = tempShift.Val;
Initialization of structures should be byte-by-bye, no need to write simple initializers like:
const somestruct mystruct = {"Field1", 2, 4, 8 .... };
do not hesitate to do so, memset for losers, and this is real money
gDataBuffer[0] = 0xEB; //Jump instruction
gDataBuffer[1] = 0x3C;
gDataBuffer[2] = 0x90;
gDataBuffer[3] = 'M'; //OEM Name "MCHP FAT"
gDataBuffer[4] = 'C';
gDataBuffer[5] = 'H';
gDataBuffer[6] = 'P';
gDataBuffer[7] = ' ';
gDataBuffer[8] = 'F';
gDataBuffer[9] = 'A';
gDataBuffer[10] = 'T';
gDataBuffer[11] = 0x00; //Sector size
gDataBuffer[12] = 0x02;
gDataBuffer[13] = disk->SecPerClus; //Sectors per cluster
gDataBuffer[14] = 0x20; //Reserved sector count
gDataBuffer[15] = 0x00;
disk->fat = 0x20 + disk->firsts;
gDataBuffer[16] = 0x02; //number of FATs
gDataBuffer[17] = 0x00; //Max number of root directory entries - 512 files allowed
gDataBuffer[18] = 0x00;
gDataBuffer[19] = 0x00; //total sectors
gDataBuffer[20] = 0x00;
gDataBuffer[21] = 0xF8; //Media Descriptor
gDataBuffer[22] = 0x00; //Sectors per FAT
gDataBuffer[23] = 0x00;
gDataBuffer[24] = 0x3F; //Sectors per track
gDataBuffer[25] = 0x00;
gDataBuffer[26] = 0xFF; //Number of heads
gDataBuffer[27] = 0x00;
// Hidden sectors = sectors between the MBR and the boot sector
gDataBuffer[28] = (BYTE)(disk->firsts & 0xFF);
gDataBuffer[29] = (BYTE)((disk->firsts / 0x100) & 0xFF);
gDataBuffer[30] = (BYTE)((disk->firsts / 0x10000) & 0xFF);
gDataBuffer[31] = (BYTE)((disk->firsts / 0x1000000) & 0xFF);
// Total Sectors = same as sectors in the partition from MBR
gDataBuffer[32] = (BYTE)(secCount & 0xFF);
gDataBuffer[33] = (BYTE)((secCount / 0x100) & 0xFF);
gDataBuffer[34] = (BYTE)((secCount / 0x10000) & 0xFF);
gDataBuffer[35] = (BYTE)((secCount / 0x1000000) & 0xFF);
gDataBuffer[36] = fatsize & 0xFF; //Sectors per FAT
gDataBuffer[37] = (fatsize >> 8) & 0xFF;
gDataBuffer[38] = (fatsize >> 16) & 0xFF;
gDataBuffer[39] = (fatsize >> 24) & 0xFF;
gDataBuffer[40] = 0x00; //Active FAT
gDataBuffer[41] = 0x00;
gDataBuffer[42] = 0x00; //File System version
gDataBuffer[43] = 0x00;
gDataBuffer[44] = 0x02; //First cluster of the root directory
gDataBuffer[45] = 0x00;
gDataBuffer[46] = 0x00;
gDataBuffer[47] = 0x00;
gDataBuffer[48] = 0x01; //FSInfo
gDataBuffer[49] = 0x00;
gDataBuffer[50] = 0x00; //Backup Boot Sector
gDataBuffer[51] = 0x00;
gDataBuffer[52] = 0x00; //Reserved for future expansion
gDataBuffer[53] = 0x00;
gDataBuffer[54] = 0x00;
gDataBuffer[55] = 0x00;
gDataBuffer[56] = 0x00;
gDataBuffer[57] = 0x00;
gDataBuffer[58] = 0x00;
gDataBuffer[59] = 0x00;
gDataBuffer[60] = 0x00;
gDataBuffer[61] = 0x00;
gDataBuffer[62] = 0x00;
gDataBuffer[63] = 0x00;
gDataBuffer[64] = 0x00; // Physical drive number
gDataBuffer[65] = 0x00; // Reserved (current head)
gDataBuffer[66] = 0x29; // Signature code
gDataBuffer[67] = (BYTE)(serialNumber & 0xFF);
gDataBuffer[68] = (BYTE)((serialNumber / 0x100) & 0xFF);
gDataBuffer[69] = (BYTE)((serialNumber / 0x10000) & 0xFF);
gDataBuffer[70] = (BYTE)((serialNumber / 0x1000000) & 0xFF);
gDataBuffer[82] = 'F';
gDataBuffer[83] = 'A';
gDataBuffer[84] = 'T';
gDataBuffer[85] = '3';
gDataBuffer[86] = '2';
gDataBuffer[87] = ' ';
gDataBuffer[88] = ' ';
gDataBuffer[89] = ' ';
4. Inventing a bike or money out of spaces
The idea of the FileObjectCopy function in the file “MDD File System \ FSIO.c” on line 6065 led me to another thought, I suspect that if they had more different structures then other SomeObjectCopy would appear
function itself
void FileObjectCopy(FILEOBJ foDest, FILEOBJ foSource)
{
int size;
BYTE* dest;
BYTE* source;
int Index;
dest = (BYTE*)foDest;
source = (BYTE*)foSource;
size = sizeof(FSFILE);
for (Index = 0; Index < size; Index++) {
dest[Index] = source[Index];
}
}
Description charms with simplicity:
The FileObjectCopy function will make an exacy copy of a specified FSFILE object.If "exacy" == "exact" as follows from the code, then this is a profitable replacement for direct assignment of structures - a standard operation in ANSI C, and made by the compiler, it should be faster and more compact since hardware FSR / INDF registers are used. Memcpy (d, s, sizeof (s)) is suitable for different objects and it also works quickly, in any case, its assembler implementation.
unprofitable version of FileObjectCopy, disassembled version from HITech C18
; *FileObject1 = *FileObject2; // Одна строчка на С
; Загружаем индирект регистры
MOVLW FileObject1 >> 8
MOVWF FSR1H
MOVLW FileObject1
MOVWF FSR1L
MOVLW FileObject2 >> 8
MOVWF FSR0H
MOVLW FileObject2
MOVWF FSR0L
; Копируем
MOVLW sizeof(*FileObject)
loop:
MOVFF POSTINC0, POSTINC1 ; Три команды процессора на скпированный байт
DECFSZ WREG, F
BRA loop
Well, there are still little things for inflating the code, with which you can add a couple - three lines, such as:
int FSerror (void)
{
return FSerrno;
}
Even if it is solely to make the read-only variable, then such a macro is quite enough for the compiler to swear where necessary:
#define FSerror() ( FSerrno )
5. Comments with fanaticism
Comment on everything except the most unintelligible pieces (see Example 1.) If you have not yet reached full enlightenment and two or three functions have accidentally remained in your Hindu program - create a “function description template”, include smart section words in the section "Description" list again everything that was written above, but expanded. Especially the effect of multiplying lines of code is manifested with functions like “FSerror ()” from the example above.
even an empty hat looks significant
/**************************************************************************
Function:
void func (void)
Summary:
Does a hard work
Conditions:
This function should not be called by the user
Input:
None
Return Values:
None
Side Effects:
None
Description:
This function will do , with input parameter....
Remarks:
Optimize code later
**************************************************************************/
6. Use features of architecture
All that has been written above is general advice for beginners on the path to enlightenment, applicable to any program, in almost any language. But real Shiva fans use every opportunity to create chaos. Given the curvature of the Harvard architecture of PIC controllers, the real gurus of the Hindu code will discover an unbelievable number of possibilities for using specific directives and other features of the curvature of the C implementation in compilers.
Write the code in such a way that it cannot even compile under different versions of compilers, and use all the specific #pragma. In this case, each function will be present in versions for at least two compilers and three to four PIC architectures, for a total of up to 8 times the code increase.
It will help you to double the amount of code once again that the RAM and ROM pointers in the compilers for PIC are different, that is, “char *” cannot be converted explicitly or implicitly to “const char *” in high tech or “const rom char *” in microchip . Which, in general, does not cause any problems at all in high-tech, since void, far and const pointers can address all memory and apply to both ROM and RAM. But in the microchip implementation of si, this can lead to the creation of two functions: one working with ROM, and the second with RAM - pure profit. You should never be content with one function that works with RAM (and, if necessary, loads constants from ROM there).
And finally, always use inline assembler even in cases when your code is much longer and slower than what the compiler does from a normal C program. Assembler looks cool and most will not suspect the poor folly that was applied when it was created, and they will also assume that the program is written as one of the best possible methods.
Instead of a conclusion
Trying to make the microchip miracle work (their site still rose) I spent a little more time than the one for which I wrote my implementation of working with SD and ported the file system taken here , which I warn you about - more accurately: “glitch inside”.