The Basics |
The nano virtual machine is register based. The're 32 registers for long int and 32 registers for double numbers. The math opcodes use the registers. So a variable or constant has to be pushed into a register before a operation. To do this we need the "push" opcode: push_i 10, L0;Pushes the constant "10" into register "L0". To write a register to a variable, we need the "pull" opcode: pull_i L0, x;Pulls register "L0" into the short int variable "x". Lets see this in an example. We want to calculate "77 * 88" and store the result in variable "x". The line numbers are for reference only, they are not a part of the program. calc_1.na 1| int x; 2| 3| push_i 77, L0; 4| push_i 88, L1; 5| mul_l L0, L1, L2; 6| pull_i L2, x; 7| 8| push_i 0, L4; 9| exit L4;The first line declares the variable "x" as "int". In line 5 we do the multiplication: "L2 = L0 * L1". Note the "L" before a register means "long int". So we need the "mul_l" opcode there. Line 9 exits the program and sets a return value for the shell environment. We set "0", so it means no error. Note: NEVER FORGET THE "exit" OPCODE! THIS IS IMPORTANT! You also have to take care that the program flow reaches the "exit" opcode! This example has some drawback, we can't see the result. We need to print it on the screen. Here comes the "print" opcode into play: print_l L2;As you can see, it's simple to use. Only the right register is needed. But we want to print a "new line" after the result, to get a formatted output: push_i 1, L3; print_n L3;The "print_n" opcode prints the number of newlines as set in the register. Here's the new program: calc_2.na 1| int x; 2| 3| push_i 77, L0; 4| push_i 88, L1; 5| mul_l L0, L1, L2; 6| pull_i L2, x; 7| 8| print_l L2; 9| push_i 1, L3; 10| print_n L3; 11| 12| push_i 0, L4; 13| exit L4; OpcodesL = long register, D = double register BV = byte variable, IV = int variable, LV = long int variable DV = double variable, SV = string variable V = variable, N = integer variable {} = optional (arrays) variable declarationbyte BV{[NV]}; int IV{[NV]}; lint LV{[NV]}; double DV{[NV]}; string SV[NV]; variable, constant to registerpush_b BV, L; push_i IV, L; push_l LV, L; push_d DV, D; register to variablepull_b L, BV; pull_i L, IV; pull_l L, LV; pull_d D, DV; register to registermove_l L1, L2; L1 to L2 move_d D1, D2; D1 to D2Next: Console Input |