esimpletron.c (9799B)
1 /* Exercise 7.29 */ 2 3 /* The Extended Simpletron (and LMS) implementation */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <math.h> 9 10 #define MEMSIZE 1000 11 #define MAXWORD 7 12 13 /* Input/Output */ 14 #define READ 10 15 #define WRITE 11 16 #define NEWLINE 12 17 #define SREAD 13 18 #define SWRITE 14 19 20 /* Loading/Storing */ 21 #define LOAD 20 22 #define STORE 21 23 24 /* Arithmetical */ 25 #define ADD 30 26 #define SUBTRACT 31 27 #define DIVIDE 32 28 #define MULTIPLY 33 29 #define REST 34 30 #define POWER 35 31 32 /* Reference and control */ 33 #define BRANCH 40 34 #define BRANCHNEG 41 35 #define BRANCHZERO 42 36 #define HALT 43 37 38 int checkword(int word, int size); 39 void dump(float acc, int icounter, float mem[]); 40 int r_htoi(const char string[]); 41 char * p_itoh(int num, char str[], int z); 42 43 int main(void) 44 { 45 char s_mem[MAXWORD] = { 0 }; 46 float memory[MEMSIZE] = { 0 }, accumulator = 0; 47 48 int operationCode = 0, instructionRegister = 0, operand = 0; 49 int i, j, k, err = 0; 50 float t_val = 0, f_tmp; 51 52 printf("*** Welcome to the Simpletron! ***\n" 53 "*** Please enter your program one instruction ***\n" 54 "*** (or data word) at a time. I will type the ***\n" 55 "*** location number and a question mark (?). ***\n" 56 "*** You then type the word for that location. ***\n" 57 "*** Use the sentinel -999999 to stop entering ***\n" 58 "*** your program. ***\n"); 59 60 for(i = 0; i < MEMSIZE; i++) { 61 while(1) { 62 printf("%.2d ?? ", i); 63 scanf("%s", s_mem); 64 65 memory[i] = r_htoi(s_mem); 66 67 if(memory[i] == -999999) { 68 memory[i] = 0; 69 i = MEMSIZE; /* Terminate the for loop */ 70 break; 71 } 72 73 if(s_mem[0] != '+') { 74 printf("*** Invalid instruction: %s\n", s_mem); 75 printf("*** Please use '+' or exit.\n"); 76 continue; 77 } 78 79 if( checkword((int)memory[i], MEMSIZE) ) { 80 printf("*** Invalid instruction: +%.0f\n" 81 "*** Please retype it or exit.\n", memory[i]); 82 } 83 else 84 break; 85 86 } /* end while */ 87 } /* end for (i) */ 88 89 printf("*** Program loading completed ***\n" 90 "*** Program execution begins ***\n"); 91 92 for(i = 0; i < MEMSIZE; i++) { 93 instructionRegister = (int)memory[i]; 94 95 operationCode = 96 instructionRegister / (instructionRegister <= 9999 ? 100 : 1000); 97 operand = 98 instructionRegister % (instructionRegister <= 9999 ? 100 : 1000); 99 100 /* this is required because after the switch() 101 statement the 'i' counter is incremented of 1. */ 102 if(operationCode >= BRANCH) 103 --operand; 104 105 switch(operationCode) { 106 case READ: 107 printf("\nInsert a word: "); 108 scanf("%f", &memory[operand]); 109 110 break; 111 case WRITE: 112 printf("\nMemory location: %.2d\nWord: %.2f\n", 113 operand, memory[operand]); 114 115 break; 116 case NEWLINE: 117 printf("\n"); 118 break; 119 case SREAD: 120 /* If this instruction is used then HALT is required */ 121 printf("\nInsert a string: "); 122 scanf("%s", s_mem); 123 124 if(strlen(s_mem) > 3) { 125 err = 3; 126 break; 127 } 128 129 for(j = 0; (unsigned)j < strlen(s_mem); j++) { 130 if((int)s_mem[j] > 99) { 131 err = 4; 132 t_val = j; 133 break; 134 } 135 } 136 memory[operand] = 0; 137 138 for(j = strlen(s_mem), k = 1; j >= 0; k *= 100, j--) 139 memory[operand] += s_mem[j] * k; 140 141 for(t_val = 0.1, k = 1; k < memory[operand]; t_val *= 0.10, k *= 10) ; 142 t_val /= 0.10; 143 144 memory[operand] *= t_val; 145 memory[operand] += strlen(s_mem); 146 147 break; 148 case SWRITE: 149 printf("\nMemory location: %.0f\nWord: ", memory[operand]); 150 for(j = (int)memory[operand], t_val = 100; j ; t_val *= 100, j--) { 151 f_tmp = memory[operand] * t_val; 152 k = (int)f_tmp % 100; 153 printf("%c", k); 154 } 155 printf("\n"); 156 157 break; 158 case LOAD: 159 accumulator = memory[operand]; 160 break; 161 case STORE: 162 memory[operand] = accumulator; 163 break; 164 165 case ADD: 166 accumulator += memory[operand]; 167 168 break; 169 case SUBTRACT: 170 accumulator -= memory[operand]; 171 172 break; 173 case DIVIDE: 174 if( !memory[operand] ) 175 err = 2; 176 else 177 accumulator /= memory[operand]; 178 179 break; 180 case MULTIPLY: 181 accumulator *= memory[operand]; 182 183 break; 184 case REST: 185 accumulator = (int)accumulator % (int)memory[operand]; 186 187 break; 188 189 case POWER: 190 accumulator = pow(accumulator, memory[operand]); 191 break; 192 193 case BRANCH: 194 i = operand; 195 break; 196 case BRANCHNEG: 197 if(accumulator < 0) 198 i = operand; 199 200 break; 201 case BRANCHZERO: 202 if(!accumulator) 203 i = operand; 204 205 break; 206 207 case HALT: 208 i = MEMSIZE; /* terminate the for loop */ 209 /* dump(accumulator, i, memory); */ 210 211 break; 212 case 0: 213 break; 214 215 default: 216 printf("*** unknown error: %d\n", instructionRegister); 217 dump(accumulator, i, memory); 218 printf("\nAre'nt you using HALT (+4300)?\n"); 219 exit(-1); 220 } 221 222 if(accumulator > MEMSIZE * MEMSIZE - 1 || 223 accumulator < MEMSIZE * -MEMSIZE + 1) 224 err = 1; 225 226 if(err) { /* Error messages manager */ 227 printf("\n*** "); 228 switch(err) { 229 case 1: 230 printf("Out of the accumulator limit"); 231 break; 232 case 2: 233 printf("Attempt to divide by zero"); 234 break; 235 case 3: 236 printf("You can put max 3 numbers for memory location"); 237 break; 238 case 4: 239 printf("This ASCII code is too long: %d (%c)", 240 s_mem[(int)t_val], s_mem[(int)t_val]); 241 } 242 243 printf(" ***\n"); 244 245 printf("*** Simpletron execution abnormally terminated ***\n"); 246 dump(accumulator, i, memory); 247 exit(-1); 248 } 249 250 } /* end for (i) */ 251 252 /* dump(accumulator, i, memory); */ 253 printf("\n*** Simpletron execution terminated ***\n"); 254 255 return 0; 256 } /* E0F main */ 257 258 /* Check if a "word" is correct */ 259 int checkword(int word, int size) 260 { 261 if( word < 0 || word >= MEMSIZE * MEMSIZE || 262 word % (word <= 9999 ? 100 : 1000) >= size ) { 263 return 1; 264 } 265 266 switch(word / (word <= 9999 ? 100 : 1000)) { 267 case READ: 268 case WRITE: 269 case NEWLINE: 270 case SREAD: 271 case SWRITE: 272 case LOAD: 273 case STORE: 274 case ADD: 275 case SUBTRACT: 276 case DIVIDE: 277 case MULTIPLY: 278 case REST: 279 case POWER: 280 case BRANCH: 281 case BRANCHNEG: 282 case BRANCHZERO: 283 case HALT: 284 case 0: 285 break; 286 default: 287 return 1; 288 289 } /* end switch (word) */ 290 291 return 0; 292 293 } /* eof checkword() */ 294 295 /* Show a dump of the current memory state */ 296 void dump(float acc, int icounter, float mem[]) 297 { 298 int i, j; 299 char string[6] = { 0 }; 300 301 printf("\nREGISTERS:\n"); 302 303 printf("accumulator\t\t%c%s\n", acc < 0 ? '-' : '+', p_itoh(acc, string, 4)); 304 printf("instructionCounter\t%s\n", p_itoh(icounter, string, 2)); 305 306 printf("instructionRegister\t%c%s\n", mem[icounter] < 0 ? '-' : '+', 307 p_itoh(mem[icounter] < 0 ? -mem[icounter] : mem[icounter], string, 4)); 308 309 printf("operationCode\t\t%s\n", p_itoh(mem[icounter] / 100, string, 2)); 310 printf("operand\t\t\t%s\n", p_itoh((int)mem[icounter] % 100, string, 2)); 311 312 printf("\nMEMORY:\n"); 313 314 /* Print the header */ 315 printf("%3c", ' '); 316 for(i = 0; i < 10; i++) 317 printf("%5d ", i); 318 printf("\n"); 319 320 for(i = 0; i < MEMSIZE; i += 10) { 321 printf("%.3d", i); 322 for(j = i; j < i+10; j++) { 323 printf(" %c%s", mem[j] < 0 ? '-' : '+', 324 p_itoh(mem[j] < 0 ? -mem[j] : mem[j], string, 4)); 325 } 326 printf("\n"); 327 } 328 329 } /* eof dump() */ 330 331 int r_htoi(const char string[]) 332 { 333 int i, num = 0, n = 1; 334 char s[1] = { 0 }; 335 336 for(i = strlen(string) - 1; i >= 0; i--) { 337 if(string[i] >= 'A' && string[i] <= 'F') 338 n *= 10; 339 340 n *= 10; 341 } 342 343 n /= 10; 344 345 for(i = 0; i < 7; n /= 10, i++) { 346 347 if(string[i] >= 'A' && string[i] <= 'F') { 348 num += 1 * n; 349 n /= 10; 350 } 351 352 switch(string[i]) 353 { 354 case 'A': 355 case 'a': 356 /* 0 */ 357 break; 358 case 'B': 359 case 'b': 360 num += 1 * n; 361 break; 362 case 'C': 363 case 'c': 364 num += 2 * n; 365 break; 366 case 'D': 367 case 'd': 368 num += 3 * n; 369 break; 370 case 'E': 371 case 'e': 372 num += 4 * n; 373 break; 374 case 'F': 375 case 'f': 376 num += 5 * n; 377 break; 378 default: 379 *s = string[i]; 380 if(string[0] == '-') 381 num -= atoi(s) * n; 382 else 383 num += atoi(s) * n; 384 } /* end switch */ 385 386 } 387 388 return num; 389 } 390 391 char * p_itoh(int num, char str[], int z) 392 { 393 int i, idx = 0; 394 395 if(num > 0) { 396 if(num <= 9) i = 1; 397 else if(num <= 99) i = 10; 398 else if(num <= 999) i = 100; 399 else if(num <= 9999) i = 1000; 400 else if(num <= 99999) i = 10000; 401 else { 402 printf("error in p_itoh(): unknown range: %d\n", num); 403 printf("\nAre'nt you using HALT (+4300)?\n"); 404 exit(-1); 405 } 406 } 407 else if(!num) { 408 for(i = 0; i < (int)sizeof(str); i++) { 409 if(i < z) str[i] = '0'; 410 else str[i] = ' '; 411 } 412 return str; 413 } 414 else { 415 printf("Negative numbers are not allowed!\n"); 416 return 0; 417 } 418 419 for( ; i ; idx++, i /= 10) { 420 421 if( (num / i % 10) == 1 ) { 422 423 i /= 10; 424 if(!i) break; 425 switch(num / i % 10) { 426 case 0: 427 str[idx] = 'A'; 428 break; 429 case 1: 430 str[idx] = 'B'; 431 break; 432 case 2: 433 str[idx] = 'C'; 434 break; 435 case 3: 436 str[idx] = 'D'; 437 break; 438 case 4: 439 str[idx] = 'E'; 440 break; 441 case 5: 442 str[idx] = 'F'; 443 break; 444 default: 445 str[idx] = (char)(num / i % 10) + '0'; 446 i *= 10; 447 } 448 } 449 450 else { 451 str[idx] = (char)(num / i % 10) + '0'; 452 } 453 } /* end for (i) */ 454 455 return str; 456 } 457