Microchipのヒンドゥー教コード

SDカードをマイクロコントローラーにすばやく接続する必要があり、タスクは簡単に思えました-優れたマイクロチップはすべてのライブラリを提供します(ああ、ライブラリにリンクを置くのは運命ではありません)、コードを最初に見てから頭の毛が動き始めました。



マイクロチップのサポートと話した人は、おそらく彼らがオフィスのインドの部門に陥ることにしばしば気づきました。マイクロチップ全体がすぐにボンベイに移動し、インドのホームレスの学童を募集して図書館を書くという疑いがなければ、何もありません。







私は人種的に正しいラインを曲げようとしているとは思わない-私は特にインド人との経験がありませんでしたが、私たちの人々の中に十分な人がいることは確かです(信じないでください、Googleで「95」と入力してください )政治的に正しいWikipediaで見つけることはできませんが、しっかりと定着しています(googolは確かにそれを知っています)。

ヒンドゥー教のコード (インドやネイティブアメリカンではありません)は、単純だが悪質なコピーペーストの原則を使用した非常に低品質のコードの俗語です。

なぜヒンズー教徒なのか

インドの噂によると、しばらくの間、記述されたコードの量に基づいてプログラマーの生産性を評価する慣行がありました。 コードが多ければ多いほど、プログラマーの仕事量が多くなるため、彼の給与は高くなります。 軽快なインディアンは、未熟な顧客をだます方法をすぐに見つけました。

kaladharaからの便利なメモ

インドの居住者はインド人であり、ヒンズー教徒はヒンドゥー教のあらゆる方向の支持者です。 したがって、シャイビズムを公言する(そしておそらくC ++で書く)上級者のチュクチでさえ、インド人です。



したがって、マイクロチップでこのようなプログラムを作成する方法を学びたい場合は、次の簡単なヒントに従ってください...



0.より多くのコード-より多くの利益!



マイクロチップで仕事を得るときに従事するときに覚えておくべき最も重要なことは、「彼らはまだコードの行にお金を払っています!」です。 したがって、何らかの方法でソーステキストの量を増やしてください。 一般的なアドバイスには、例はありませんが、ファンタジーが含まれています。



1.ジャンルの古典



ヒンドゥー教の映画のコードジャンルの古典は、当初から揺るぎないものでした。ウォームアップするには、1042行の「MDD File System \ SD-SPI.c」ファイルに含まれるこのコードの背後に隠されているものを推測してみてください。



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; }
      
      





回答を急いで見てはいけません-それは簡単です:
 //    (      )    while (localCounter--) { SPIBUF = 0xFF; while (!SPISTAT_RBF); *localPointer++ = SPIBUF; } //    ,        //      -    while (localCounter) { localCounter--; SPIBUF = 0xFF; while (!SPISTAT_RBF); *localPointer++ = SPIBUF; }
      
      







2.コピーアンドペースト



想像力がない場合、コピーペーストも適していますが、多くの雇用者はコピーペーストのコードをチェックするという噂によれば、マイクロチップは明らかにそれらの1つではありません。 覚えておいて、ヒンドゥー教のコードで生地を切るためにマクロを使用しないでください-彼らは邪悪でugいコードを減らします。 たとえば、MDD File System \ FSIO.cファイルで20回繰り返されるピース:



ctrl + v
 if (utfModeFileName) { utf16path++; i = *utf16path; } else { temppath++; i = *temppath; }
      
      





一般的に、私はプログラミングでコピーアンドペーストを我慢できません。 何かをコピーしたい場合は、すぐにどこで何を書き換えるかを考えます。 そして、関数でラップできない同じコードが必要な場合、鈍いコピーの代わりに、それからマクロを作成することができます。これは、より読みやすく、将来編集しやすくなります。



上記のピースの簡単で明確な交換
 #define getnextpathchar() ( utfModeFileName ? *++utf16path : *++temppath ) // -   ... i = getnextpathchar(); //   
      
      





最初のオプションを支持する10:1の比率であり、絶対的な用語で20回の繰り返しを考えると、これは数百ルピーです!



3.回線コード



サイクルの使用は悪です。 線形プログラムは、条件ステートメントと遷移に時間を浪費することなく、はるかに高速に実行され、より多くのコード行を含みます。



お気軽に
 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;
      
      





構造体の初期化はバイト単位で行う必要があり、次のような単純な初期化子を記述する必要はありません。



 const somestruct mystruct = {"Field1", 2, 4, 8 .... };
      
      





ためらうことなく、敗者のためのmemset、そしてこれは本当のお金です
 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.スペースから自転車やお金を発明する



6065行のファイル「MDD File System \ FSIO.c」にあるFileObjectCopy関数のアイデアから、別の考えが導かれました。さらに構造が異なると、SomeObjectCopyが表示されるのではないかと思います



機能自体
 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]; } }
      
      





シンプルで魅力的な説明:
FileObjectCopy関数は、指定されたFSFILEオブジェクトの正確なコピーを作成します。
コードから次のように「exacy」==「exact」の場合、これは構造の直接割り当ての有益な代替です-ANSI Cの標準操作であり、コンパイラによって行われ、ハードウェアFSR / INDFレジスタが使用されるため、より高速でコンパクトになります。 Memcpy(d、s、sizeof(s))はさまざまなオブジェクトに適しており、いずれにせよ、アセンブラーの実装も迅速に機能します。



FileObjectCopyの非営利バージョン、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
      
      





さて、コードを膨らませるにはまだ少しのものがあり、それをいくつか追加することができます-3行、例えば:



 int FSerror (void) { return FSerrno; }
      
      





読み取り専用変数を作成するだけの場合でも、そのようなマクロは、コンパイラが必要に応じて誓うには十分です:



 #define FSerror() ( FSerrno )
      
      







5.狂信的なコメント



最もわかりにくい部分以外のすべてにコメントします(例1を参照)。まだ完全な啓発に達しておらず、2つまたは3つの機能がヒンドゥープログラムに誤って残っている場合-「機能説明テンプレート」を作成し、セクションにスマートな単語セクションを含めます「説明」には、上記で記述されていたが展開されたすべてのものが再びリストされます。 特に、コード行の乗算の効果は、上記の例の「FSerror()」のような関数で明らかになります。



空の帽子でさえ重要に見える
 /************************************************************************** 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 <a hard work>, with <none> input parameter.... Remarks: Optimize code later **************************************************************************/
      
      







6.アーキテクチャの機能を使用する



上記に書かれているのは、ほとんどすべての言語で、あらゆるプログラムに適用できる、啓発への道に関する初心者向けの一般的なアドバイスです。 しかし、真のシヴァファンはあらゆる機会を利用して混乱を生み出します。 PICコントローラーのハーバードアーキテクチャの曲率を考えると、ヒンドゥー教のコードの本当の達人は、コンパイラーのC実装の曲率の特定のディレクティブやその他の機能を使用するための信じられないほどの可能性を発見します。



異なるバージョンのコンパイラーでもコンパイルできないような方法でコードを記述し、特定の#pragmaをすべて使用します。 この場合、各関数は少なくとも2つのコンパイラーと3〜4つのPICアーキテクチャーのバージョンに存在し、合計で最大8倍のコード増加になります。



コード量を2倍にするために、PICコンパイラーのRAMポインターとROMポインターは異なります。つまり、「char *」を明示的または暗黙的にハイテクの「const char *」またはマイクロチップの「const rom char *」に変換できません。 。 void、far、constポインタはすべてのメモリをアドレス指定でき、ROMとRAMの両方に適用できるため、一般にハイテクでは問題を引き起こしません。 しかし、siのマイクロチップ実装では、これは2つの関数の作成につながる可能性があります。1つはROMで動作し、もう1つはRAMで動作します-純粋な利益。 RAMで動作する1つの関数に満足することはありません(必要に応じて、そこからROMから定数をロードします)。



最後に、コンパイラが通常のCプログラムから実行するものよりもコードがはるかに長くて遅い場合でも、常にインラインアセンブラを使用します。 アセンブラーはクールに見え、ほとんどの場合、作成時に適用された愚かな愚かさを疑うことはありません。また、プログラムは可能な限り最良の方法の1つとして書かれていると想定します。



結論の代わりに



マイクロチップの奇跡を働かせようとして(そのサイトはまだ上昇していました)、 SDでの作業とここで取り上げたファイルシステムの移植の実装を書くよりも少し時間を費やしました。



All Articles