Thursday, May 23, 2013

SCC11. SmallC - PMI80

Neuveriteľné (pre mňa) sa stalo skutočnosťou. Na jednodoskáči s klávesnicou a sedemsegmentovým displayom beží program napísaný v C. Trocha to rozpíšem. Jedná sa o PMI80. Ten program v C sa samozrejme nezadáva cez klávesnicu a ani sa nekompiluje na PMI80. Program sa kompiluje pomocou SmallC na PC a napáli sa do EPROM. Je to o dosť zdĺhavejšie ako mať k dispozícii veľkú RAM a sériový bootloader. Práve preto som kedysi postavil NCB85.

Tu beží program v C
Istý Jakub si na aukro.cz kúpil toto PMI80 z obrázku. A nedalo mu to, skúsil na ňom C spôsobom ako som opísal. A nutno povedať, že s úspechom.


Data a Code segmenty
Pri preklade do RAM je vcelku jedno, kde sa nachádza program a kde premenné. Iné je to ale pri použití ROM. Program je v ROM, pretože jeho obsah je pevne daný a nemení sa. Ak teda zrovna nepoužívame samomodifikujúci sa kód. Ale premenné musia byť v RAM. Na toto majú assemblery možnosť definíce dátového a kódového segmentu alebo aj ďalších segmentov. Linker potom priradí každému segmentu adresu a vygeneruje správne skoky a návestia. Ja som nazval v SmallC dátový a programový segment takto:
Programový kód je umístěn do oblasti uvozené:
.area SMALLC_GENERATED (REL,CON,CSEG)
globální proměnné pak do:
.area SMALLC_GENERATED_DATA (REL,CON,DSEG)
Jakub poslal aj popis ako sú uložené dáta a program.
Lokální proměnné jsou jako obvykle umísťovány na stacku. Pro použití s PMI-80 je potřeba oblast SMALLC_GENERATED_DATA přesměrovat někam mezi adresy 0x1c00 a 0x1fff, kde je jediný 1KB RAM (přičemž je třeba mít na zřeteli, že od konce RAM směrem dolů roste stack). Já programová data umísťuji od adresy 0x0800 kde na mém upraveném PMI začíná třetí KB ROM a je to začátek druhého EPROM čipu. Programy do PMI dostávám pomocí mazačky a programátoru EPROM. Majitel neupraveného PMI bude muset linkovat na adresu 0x0400, nebo také do RAM (ale opravdu jí není mnoho). Já zatím do RAM program nelinkoval, protože stejně zatím nemám žádný loader, kterým bych ho bez použití naprogramované EPROM dostal na místo.
takto vyzerá výpis na display
update_disp(mpx,seg)
   unsigned char mpx;
   unsigned char seg;
   {
     mpx;
#asm
     mov b,l
#endasm
     seg;
#asm
     mov a,l
     out 0xF8
     mov a,b
     out 0xFA
#endasm
   }
a takto krátený hlavný program
for (a = 0; a < 37; a++) { //pres celou tabulku znaku v kodu monitoru
   disp_buff[0] = (a >> 4) & 0x0f;
   disp_buff[1] = (a ) & 0x0f;
   disp_buff[2] = PMI_CH_equal;
   bin2bcd(a, &disp_buff[3]);
   disp_buff[6] = PMI_CH_equal;
   disp_buff[7] = PMI_CH_equal;
   disp_buff[8] = a;

   for (c = 0; c < 100; c++) {
     for (b = 0; b < 9; b++) {
       update_disp(~b, seg_data[disp_buff[b]]);
       delay(10);
     }
   }
}
C na PMI80. Kto by si to bol kedy pomyslel ? Kto by mal záujem o podobné hrátky bude sa musieť spojiť s Jakubom. Ja PMI80 nevlastním ;-)

Saturday, May 11, 2013

SCC.10 printf

printf je užitočná a pomerne silná metóda, ktorá je prítomná v prekvapujúco veľa jazykoch. Okrem iných aj Fortran, Cobol, Java, PHP, Perl .. Mňa na nej vždy fascinovalo to, že má premenlivý počet parametrov. Napríklad:

printf("V zivote je %d dobrých vecí, hlavne %s stojí za to", my_number, her_name);

V tomto prípade má 3 parametre. Prvý je string obsahujúci formattery a nasledujú hodnoty pre formattery. Prvý je číslo ktorá sa zobrazí v decimálnom tvare a druhý parameter je string ktorý sa len prekopíruje na zodpovedajúcu pozíciu. Dlho som si lámal hlavu nad tým, ako len môže byť printf napísaný ... Veď čo ak by tie parametre boli štyri alebo povedzme sedem prípadne iba jeden ? Dosť záhadné :-)

Tajomstvo printf je jednoduché. C robí PUSH parametrov metódy na zásobník v opačnom poradí. Najskôr sa PUSHne posledný param a potom druhý od konca a tak ďalej. Až na koniec sa PUSHne prvý parameter. A to znamená, že sa nachádza hneď nad návratovou adresou, ktorú PUSHlo volanie našej metódy CALL printf

Preto stačí v implementácii printf získať obsah dvoch byte nad aktuálnym SP. To bude pointer na string obsahujúci formattery. A sme doma :-) Pretože z toho stringu už vieme zistiť koľko parametrov má naše volanie printf. A každý z nich sa nachádza zase o dva bytes vyššie.

Metóda printf nie je súčasťou SmallC, ale nie je problém ju napísať. Ja sa na to chystám už mesiac ;-) Sú tu ale dve veci. Dobrá a zlá. Zlá správa je, že v SmallC sa parametre volania ukladajú na stack v opačnom poradí ako je špecifikácia C. Čiže pascalovským spôsobom a tým pádom bude formátovací string najďalej od SP. Takže sa to nedá ? Ale dá, je tu aj dobrá správa. SmallC vie posielať do volanej metódy okrem parametrov (ktoré su PUSHnuté na stacku) aj počet parametrov. Posiela sa v ACC. Takže SmallC implementácia bude neštandardná. Počet parametrov si nezistí sama, ale bude sa spoliehať na číslo v ACC.

Aby to bolo úplne cool, bolo by fajn napísať to celé v ASM. Ak by to niekto chcel urobiť, môžem mu poslať nejaké podklady.