Tenshi C
- This article is not detailed enough and needs to be expanded. Please help us by adding some more information.
Tenshi C or TenC is an esolang created by User:Richard565
This language is an implementation of a small subset of C to work on a custom runtime(A move architecture instruction set) he wrote in JavaScript. He named it after the song from K-ON! tenshi ni fureta yo.
History
Originally he had planned to write a C compiler for his 24 bit CPU. But he believed that it was not satisfactory and so came of it Tenshi C. The runtime and simple compiler that comes with Tenshi C created was originally meant for his portfolio but it didn't work out. The original intent was to make a simple Operating System with as few C features as possible or tolerable. While the language is usable for Operating system development. It is not recommended.
Features and Quirks
The most notable difference between Tenshi C and regular C is it's pointers. The pointers do not increment automatically by the size of a type.
Also pointers are dereferenced differently.
//regular C int * s = (int*) (5+1); //s=9 *s // normal dereference *((int*)s) // normal dereference *s = 0; // sets memory at s to 0 //Tenshi C WORD s = (WORD) (5+1); //s=6 ((WORD)*s) // dereferences a word of data which is 28 bits ((BYTE)*s) // dereferences a byte of data which is 8 bits ((DBYTE)*s) //dereferences 16 bits (WORD) *(s) = 0; //sets memory location at s which stores a memory location to 0 //WORD is the size of a pointer and can be treated as a pointer varible
A WORD is 28 bits
A DBYTE is 16 bits
A BYTE is 8 bits
What's not implemented
These are features omitted to keep the language more simple or they where omitted out of laziness.
- switch and do while loops
- error correction: Open the console for errors. Error's have not been fully implemented
- array's(there is a different syntax that is used)
- enums,typedef and macros(# is used for a different type of syntax)
Examples
Hello world
//an example hello world without libc
BYTE hello_world ="Hello World!!!"; // a varible storing the string
WORD main(){
WORD s = 0;
while( (BYTE) * (s+$hello_world) != 0 ){ // loops through hello_world and writes it to the MMIO screen.
(BYTE) *(s) = (BYTE) * (s + $hello_world);
s=s+1;
}
}
Alternate Hello world
//an example hello world without libc
WORD main(){
WORD hello_world ="Hello World!!!"; // a pointer to a varible storing the string
WORD s = 0;
while( (BYTE) * (s+hello_world) != 0 ){ // loops through hello_world and writes it to the MMIO screen.
(BYTE) *(s) = (BYTE) * (s + hello_world);
s=s+1;
}
}
Tutorial
This tutorial is meant for those who have some experience with C.
Sizes
- BYTE 8 bits
- DBYTE 16 bits
- WORD 28 bits(Per the limits of base javascript)
Varibles
WORD global_var = 0;// hello I'm a global varible
WORD main(){
DBYTE local_var = 0; // hello I'm a local varible
}
Expressions
//you cannot use Expressions to declare varibles in the global scope.
//all bitwise instructions are in the same presedence as multiplication and division
WORD main(){
WORD i = 7;
WORD local_var = (50+2*i)-3; //an example of an expression
WORD sd = asm_d("PSH 90"); // an example of an assembly block being used as an expression. The last thing pushed on the stack will actually be the result. So sd = 90
}
Structures
//structs are basically offsets to a pointer to acces data
struct person{
WORD name;
WORD bounty;
}
WORD main(){
(struct person) 0x501.name = "Arlong";
(struct person) 0x501.bounty = 20000000;
}
Conditions and loops
//there's no switch statements yet
//there is not a && or a || because booleans are expressions in assembly it's only a single comaprision
WORD main(){
if(1==1){
//do what's inside
}else if(1==1){
//do what's inside
}else{
//do what's inside
}
for(WORD s =0; s< 90; s++){
//do whats inside
}
WORD s = 0;
while(s<90){
//no "+="
s++;
}
}
Functions,Subroutines, Procedures
WORD main(){
print_z(return_nine()); // prints a Z at the nineth position.
}
//Functions can be marked WORD,BYTE,DBYTE but the lanugage ignores this. It's more like a label.
//All functions don't need to return a value.
// all parameters are words
WORD return_nine(){
return 9;
}
WORD print_z(WORD where){
(BYTE) *(where) = 90;
}
Function pointers
WORD write_z(){
(BYTE) *(0) = 90;
}
WORD main(){
WORD func_ptr = $write_z; // can only call functions above them because it is a one pass on memory counter
#fup (func_ptr).(); // #fup is the function pointer call.
}
What libC includes
// This is the small libC that comes with the implementation
//you must copy and paste this bellow the main program
BYTE strcmp(WORD str,WORD strp){
WORD cond = strlen(str) ^ strlen(strp);
WORD de = 0;
while(de <strlen(str)){
cond = cond + ((BYTE) * (str+de)) ^ ((BYTE) * (strp+de));
de = de +1;
}
return cond;
}
BYTE memset(WORD dest,WORD c, WORD ammt){
WORD de = dest;
while(de<(dest+ammt)){
(BYTE) *(de) = c;
de = de +1;
}
}
BYTE memcpy(WORD src,WORD dest, WORD ammt){
WORD de = 0;
while(de<ammt){
(BYTE) *(de+dest) = (BYTE) *(de+src);
de = de +1;
}
}
BYTE strcpy(WORD dest,WORD src){
WORD de = 0;
while((BYTE) *(de+src) != 0 ){
(BYTE) *(de+dest) = (BYTE) *(de+src);
de = de +1;
}
}
BYTE str_arr_ind(WORD str_ptr,WORD index){
WORD de = 0;
WORD int_ind = 0;
while(int_ind != index){
while((BYTE)*(str_ptr+de) != 0){
de = de+1;
}
while((BYTE)*(str_ptr+de) == 0){
de = de+1;
}
int_ind= int_ind+1;
}
return de+str_ptr;
}
BYTE strlen(WORD src){
WORD len = 0;
while((BYTE) *(len+src) != 0 ){
len = len +1;
}
return len;
}
BYTE pow(WORD base, WORD exp){
WORD de = 1;
WORD result = base;
while(de<exp){
result = result *base;
de = de +1;
}
return result;
}
BYTE stoi(WORD str_ptr){
WORD string_length = strlen(str_ptr);
WORD de =0;
WORD final_num = 0;
while(de < string_length){
final_num = final_num + (((BYTE)*(str_ptr+de)) ^48) * pow(10,(string_length -de));
de = de+1;
}
return final_num/10;
}
BYTE atoi(WORD num){
WORD buffer = "18446744073709551616";
WORD dnum = num;
WORD i=1;
WORD buf_len = strlen(buffer);
while(i < buf_len){
(BYTE) *(buffer + buf_len - i) = dnum % 10;
(BYTE) *(buffer + buf_len - i) = 48 ^ (BYTE)*(buffer + buf_len - i);
dnum = dnum / 10;
i = i + 1;
}
(BYTE) *(buffer + buf_len - i) = dnum % 10;
(BYTE) *(buffer + buf_len - i) = 48 ^ (BYTE)*(buffer + buf_len - i);
dnum = dnum / 10;
i = i + 1;
return buffer;
}
BYTE clrscr(){
memset(0,32,1024);
}
BYTE malloc(WORD tsize){
WORD i =0;
WORD k =0;
WORD heap_loc = 0x01FFFFF;
while((BYTE) *(heap_loc+i) == 1){
if((BYTE) *(heap_loc+i) == 0){
(BYTE)*(k) = 90;
k=k+1;
if( 0 == (WORD) *(heap_loc+i+1)){
asm_d("JMP #break_malloc");
}
if( tsize < (WORD) *(heap_loc+i+1)){
asm_d("JMP #break_malloc");
}
}
i = ((WORD) *(heap_loc+i+1)) + i;
}
asm_d("LABEL break_malloc");
(BYTE) *(heap_loc+i) = 1;
(WORD) *(heap_loc+i+1) = tsize+5;
return heap_loc+i+5;
}
BYTE realloc(WORD ptr,WORD tsize){
WORD new_blk = malloc(tsize);
WORD mov_ammt = ((WORD) *(ptr-4))-5;
memcpy(ptr,new_blk,mov_ammt);
free(ptr);
return new_blk;
}
BYTE mallocv(WORD siz_t){ //dynamically allocate a vector
WORD blk_ptr = malloc(siz_t+4);
(WORD) *(blk_ptr) = siz_t;
return blk_ptr+4;
}
BYTE reallocv(WORD ptr_blk,WORD siz_t){
WORD blk_ptr = realloc(ptr_blk-4,((WORD)*(ptr_blk-4))+siz_t+4);
(WORD) *(blk_ptr) = ((WORD)*(ptr_blk))+siz_t;
return blk_ptr+4;
}
BYTE free(WORD ptr){
if((BYTE) *(ptr+(WORD)*(ptr-4)) == 0){
(BYTE) *(ptr-4) = ((BYTE) *(ptr-4)) + (WORD) *(ptr+(WORD)*(ptr-4)+1);
}
(BYTE) *(ptr-5) = 0;
}
Operating system
Tenshi C has been used to develop a small operating system.
It's more like a monolithic program that runs with no memory protection. It is still in production and may be found in the implementation.
Shell commands
- stab [memory location] [integer byte] - similar to the poke command in old basic
- stabf [memory location start] [memory location end] [integer byte] - fills the location from that range
- help - You don't get any help
- clear - clear screen
- test - prints the letter A accross the screen
All memory locations used in commands must be written in decimal.
Memory map of the operating system 0x0000000 - 0x0000400 MMIO screen 0x0001000 - 0x0002000 MMIO IO Keyboard 0x0005000 - Start of program memory 0x01FFFFF - Start of Heap - Grows up 0x0FFFFFF -Start of stack 0x1000000 - Interrupt vector table 0x2000000 - Text Area 0x3000000 - Start of filesystem - Grows Up