Jump to content
IGNORED

Glorious People's small c compiler


dhe

Recommended Posts

9 hours ago, dhe said:
the other was this neat little hack to convert from a  char to an int.
      mychoice2 = mychoice_char - '0';   // convert single char to int!!

Careful! There be demons!

 

It's not really converting from a char (as in, the C data type of char) - as you correctly pointed out, you would use a cast for that:

int choice;
choice = (int)mychoice2; // choice is now an integer version of the char type mychoice2

 

The code you posted is converting from an ASCII value to a zero-based equivalent of the ASCII value.

 

So, if mychoice2 had the value 49 (which is the ascii code for the ascii character '1'), then the code above would subtract 48 from it (which the ascii character value for '0') and leave the result of 1, so you've converted the ASCII character value of '1' to the numeric value 1. It's a subtle, semantic (and somewhat pedantic, if I'm honest!) difference, but I thought it would point it out!

 

The compiler is clever enough to replace the char constant '0' with the value 48. So, the compiler sees the code as if you wrote it like this:

mychoice2 = mychoice_char - 48;

:thumbsup:

 

Edited by Willsy
Typos
  • Like 2
Link to comment
Share on other sites

Hi @dhe

 

Welcome to the surprising world of type conversions!

 

I wonder what c99 does with int promotion? If it follows C standard rules, all arithmetic takes place in int.
 

Arithmetic on chars first converts the char input to int. 
 

C has always allowed the most natural size to be chosen. so that int fits in a machine register. And the usual arithmetic instructions wants register-sizes inputs. 

 

Nowadays in C11, we can say uint16_t to be sure we get exactly what we want! 

 

mychoice2 = mychoice_char - '0';   // convert single char to int!!

The result of the expression is (signed) int. If you were to assign it back to a char, the result could have the range -128 to 127.  
 

Besides subtraction, you might sometimes want to scale:

char r;
int  c = (r- ‘0’) * 2 * 22 / 7;


You can see how if it did the arithmetic with just 8 bits, the multiplication would overflow. But MPY and DIV generally use register size operands.

 

If the inputs were large enough to overflow an int, you get a weird outcome.

 

I dunno what c99 gives! Internally, a 9900 MPY takes two 16 bit operands, gives 32 bits, and DIV takes it back down to 16.

 

I wonder if c99 lets that happen naturally, or if it enforces C rules and chops the result of MPY down to 16 bits before the DIV?

 

 


It’s good to explore these things, so that later you have the knowledge to debug C! 

 

 


 

 

  • Like 4
Link to comment
Share on other sites

In earlier release of c99 Clint wrote many example programs, attached is one I always loved. It mentally challenging (to me) to picture all that's happening - but it isn't much to look at on the screen. (I need to c if I can find a version of life written in c99).

 

/* A c version of the Sieve program as suggested by KNUTH
*/
#define true 1
#define false 0
#define size 8190
#define sized 8191
/**/
int flags[sized];
#asm
 AORG >8330
#endasm
int i,k,prime,count,iter,strikout;
#asm
 RORG
#endasm
main()
{ puts("10 iterations\n\n");
  iter=1;
  while(iter++<=10)
  { strikout=true;
    count=0;
    i=0;
    while(i<=size) flags[i++]=true;
    i=1;
    while(i<=size)
    { if(flags[i])
      { prime=i+i+1;
        ++count;
        if(strikout)
        { if((k=((prime*prime)-1)>>1)<size)
          while(k<=size) {flags[k]=false; k=k+prime;}
          else
          { strikout=false;
            continue;
          }
        }
      }
      ++i;
    }
    puts(" working...\n");
  }
  puts("\nDone!\n");
}

 

sieve.png

  • Like 1
Link to comment
Share on other sites

2 hours ago, dhe said:

In earlier release of c99 Clint wrote many example programs, attached is one I always loved. It mentally challenging (to me) to picture all that's happening - but it isn't much to look at on the screen. (I need to c if I can find a version of life written in c99).

 


/* A c version of the Sieve program as suggested by KNUTH
*/
#define true 1
#define false 0
#define size 8190
#define sized 8191
/**/
int flags[sized];
#asm
 AORG >8330
#endasm
int i,k,prime,count,iter,strikout;
#asm
 RORG
#endasm
main()
{ puts("10 iterations\n\n");
  iter=1;
  while(iter++<=10)
  { strikout=true;
    count=0;
    i=0;
    while(i<=size) flags[i++]=true;
    i=1;
    while(i<=size)
    { if(flags[i])
      { prime=i+i+1;
        ++count;
        if(strikout)
        { if((k=((prime*prime)-1)>>1)<size)
          while(k<=size) {flags[k]=false; k=k+prime;}
          else
          { strikout=false;
            continue;
          }
        }
      }
      ++i;
    }
    puts(" working...\n");
  }
  puts("\nDone!\n");
}

 

sieve.png

I think it is the Eratosthenes sieve. (?) 

About how long does it take to run? 

Link to comment
Share on other sites

Just now, dhe said:

It's all Clint's work. I liked the use of high speed ram also. On classic99 pumped up to make speed it finished in about 5 seconds.

Running in CPU Overdrive?

So that is about 23 times faster than normal so at normal speed ~115 seconds, 1:55 ish.

 

I am just curious so I can benchmark my compiler projects.

As I recall Small C was not too speedy in the old days but beat the heck out of BASIC. 

 

  • Like 2
Link to comment
Share on other sites

It was suppose to be an easy mission. A 14 line example from Chirlian in and out. Then the unfortunate happened.

printf("%b") for binary isn't a thing in c99, also unsigned int, is also, not a thing.

 

I found two routines, to print an int as a binary, the first shows off c99 recursion really well, I didn't have the heart to make it hacky by getting it to print 16 digits, the second, is far less elegant using a table based technique, but is easier to understand and prints all 16 binary digits.

 

#include "DSK2.STDIO"
 
external printf();
external scanf();
 
/* Global Vars */
  int i;
  int j;
 
  int k=0;    /* hold the result of out logic operation */
  char a;     /* used by Fwait                          */
 
 
main()
{
  printf(" Enter First Value:");
  scanf("%d",&i);
  printf("Enter Second Value:");
  scanf("%d",&j);
  putchar(12);
 
  printf("i=%d, j=%d\n",i,j);
  printf("1234567890abcdef \n");
  Fpb(i);
  printf("\n");
  Fpb(j);
 
  /* Logical AND */
  printf("\n \nLogical AND \n");
  Fpb(i);
  printf(" = i\n");
  Fpb(j);
  printf(" = j \n");
  k=j&i;               /* Logical AND */
  Fpb(k);
  printf(" = i & j \n");
 
  Fwait();
 
 
  /* Logical OR */
  printf("\n \nLogical OR \n");
  Fpb(i);
  printf(" = i\n");
  Fpb(j);
  printf(" = j \n");
  k=j|i;               /* Logical OR */
  Fpb(k);
  printf(" = i | j \n");
 
 
  /* Logical XOR */
  printf("\n \nLogical XOR \n");
  Fpb(i);
  printf(" = i\n");
  Fpb(j);
  printf(" = j \n");
  k=j^i;               /* Logical XOR */
  Fpb(k);
  printf(" = i ^ j \n");
 
  printf("\n");
  Fwait();
 
 
  /* Left Shift */
  printf("\n \nLeft Shift \n");
  Fpb(i);
  printf(" = i\n");
  k=i<<2;              /* LEFT Shift 2 */
  Fpb(k);
  printf(" = i << 2\n");
 
 
  /* Right Shift */
  printf("\n \nRight  Shift \n");
  Fpb(i);
  printf(" = i\n");
  k=i>>3;              /* RIGHT Shift 3 */
  Fpb(k);
  printf(" = i >> 3\n");
 
  return(0);
}  /* end of main */
 
/* functions here */
 
/* This code prints like:      */
/* 11111111                    */
/* 1100101011111000            */
/* Recursively Kewl            */
Fbinx(mynum)
int mynum;
{
    /* step 1 */
    if (mynum > 1)
        Fbinx(mynum / 2);
 
    /* step 2 */
    printf("%d", mynum % 2);
} /* end of Fbinx */
 
 
/* Lets try table driven */
Fpb(mynum)
int mynum;
{
  int a;
  int n;
  int num [20];
 
  for (n = 15; n >= 0; n--)
  {
    num[n] = 0;
  }
 
  num[15] = 32768 & mynum;
  num[14] = 16384 & mynum;
  num[13] = 8192 & mynum;
  num[12] = 4096 & mynum;
  num[11] = 2048 & mynum;
  num[10] = 1024 & mynum;
  num[9] = 512 & mynum;
  num[8] = 256 & mynum;
  num[7]=  128 & mynum;
  num[6] = 64 & mynum;
  num[5] = 32 & mynum;
  num[4] = 16 & mynum;
  num[3] = 8 & mynum;
  num[2] = 4 & mynum;
  num[1] = 2 & mynum;
  num[0] = 1 & mynum;
 
  for (n = 15; n >= 0; n--)
  {
 
    if (num[n] > 0)
      printf ("1");
    else
      printf ("0");
 
  }   /* end of for j */
}     /* end function Fpb */
 
Fwait()
{
  printf("Press any key to continue. \n\n");
  a=getchar();  /* wait to end */
}
 
/* Chirlian Example 4-9 */
/* dhe - 03182022       */

 

DSK4.CHIR49;O
DSK2.CSUP
DSK2.PRINTF
DSK2.SCANF

 

  • Like 1
Link to comment
Share on other sites

To Boldly go where no if statement is allowed.

 

I was reading some c tips, and one tip I came across was that the ternary operator can go inside a printf statement unlike an if statement.

 

Tested it out - kewl!

 

/*   Ternary Example   */
/*   dhe - 20220316   */
 
 
#include "DSK2.STDIO"
 
external printf ();
external scanf ();
 
/* Global Vars */
 
 
main ()
{
 
  int apples;
 
  apples=0;
 
  printf ("How many apples did you eat? ");
  scanf ("%d \n",&apples);
 
  printf ("You ate %d apple%s", apples, (apples>1) ? ("s.") : ("."));
 
  return(0);   /* no errors */
} /* end of main */
 
/* to boldly go where no if can go */

 

 

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...