Add string input interrupt from STDIN
This commit is contained in:
29
README.md
29
README.md
@@ -89,22 +89,22 @@ There is currently no strict checking, so be careful.
|
||||
## Directives
|
||||
|
||||
- `DECLARE` declares the first label argument to equal the second, immediate
|
||||
value, argument and is used to declare a constant for the virtual machine.
|
||||
value, argument and is used to declare a constant for the virtual machine.
|
||||
|
||||
### Operands
|
||||
|
||||
- `addi` add the first to the second argument and store the result in the third
|
||||
argument
|
||||
argument
|
||||
- `subi` subtract the first from the second argument and store the result in
|
||||
the third argument
|
||||
the third argument
|
||||
- `divi` divide the first by the second argument and store the result in the
|
||||
third argument
|
||||
third argument
|
||||
- `muli` multiply the first by the second argument and store the result in the
|
||||
third argument
|
||||
third argument
|
||||
- `shli` shift left the first argument by the number of positions given by the
|
||||
second argument and store the result in the third argument
|
||||
second argument and store the result in the third argument
|
||||
- `shri` shift right the first argument by the number of positions given by the
|
||||
second argument and store the result in the third argument
|
||||
second argument and store the result in the third argument
|
||||
- `seti` set the first register argument to the second argument
|
||||
- `int` calls the interrupt specified by the first (integer) argument
|
||||
|
||||
@@ -112,15 +112,15 @@ second argument and store the result in the third argument
|
||||
|
||||
- `jmp` jump to the label given by the first argument
|
||||
- `call` put the next statement to execute on the stack and jump to the label
|
||||
given by the first argument
|
||||
given by the first argument
|
||||
- `ret` pop the the next statement to execute off the stack, e.g. returning to
|
||||
the next execution statement before calling `call`
|
||||
the next execution statement before calling `call`
|
||||
- `lti` execute next statement if argument 1 is less than argument 2 else skip
|
||||
the next statement
|
||||
the next statement
|
||||
- `gti` execute next statement if argument 1 is greater than argument 2 else
|
||||
skip the next statement
|
||||
skip the next statement
|
||||
- `eqi` execute the next statement if argument 1 is equal to argument 2 else
|
||||
skip the next statement
|
||||
skip the next statement
|
||||
|
||||
## Memory
|
||||
|
||||
@@ -137,5 +137,8 @@ the first argument
|
||||
- `2` put value of register A as hexadecimal integer on stdout
|
||||
- `3` put the string pointed at by register A for the amount of characters
|
||||
defined by register B on stdout
|
||||
- [4..4] Input from STDIN
|
||||
- [4..5] Input from STDIN
|
||||
- `4` get a single ASCII character from STDIN and store it in register A
|
||||
- `5` get a string of a maximum length determined by register B and store it
|
||||
in the address specified by register A. After execution register B will
|
||||
contain the number of characters actually read.
|
||||
@@ -88,12 +88,22 @@ seti %A $900;
|
||||
seti %B $4;
|
||||
int $3;
|
||||
|
||||
# Jump over the interrupt
|
||||
# Call a function
|
||||
call noop_function;
|
||||
|
||||
# Echo a character
|
||||
int $4;
|
||||
int $0;
|
||||
|
||||
seti %A $10; # newline
|
||||
int $0;
|
||||
|
||||
# Echo a string
|
||||
seti %A $0;
|
||||
seti %B $10;
|
||||
int $5;
|
||||
int $3;
|
||||
|
||||
exit;
|
||||
|
||||
noop_function:
|
||||
|
||||
@@ -39,6 +39,12 @@ namespace Execute
|
||||
InterruptIndexOutOfRange(int const index);
|
||||
};
|
||||
|
||||
class OutOfMemory : public RuntimeError
|
||||
{
|
||||
public:
|
||||
OutOfMemory(int const memoryLocation, int const memorySize);
|
||||
};
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
class BadValueType : public RuntimeError
|
||||
|
||||
@@ -41,6 +41,15 @@ namespace Execute
|
||||
message += " is out of range";
|
||||
}
|
||||
|
||||
OutOfMemory::OutOfMemory(int const memoryLocation, int const memorySize)
|
||||
{
|
||||
message = "Attempted interaction at memory location ";
|
||||
message += std::to_string(memoryLocation);
|
||||
message += " with size ";
|
||||
message += std::to_string(memorySize);
|
||||
message += " failed";
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
BadValueType::BadValueType()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <cstdio>
|
||||
#include <execute/error.hpp>
|
||||
#include <execute/interrupts.hpp>
|
||||
|
||||
namespace Execute
|
||||
@@ -18,6 +19,11 @@ namespace Execute
|
||||
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||
{
|
||||
unsigned const end = registers.A + registers.B;
|
||||
if (end >= memory.size())
|
||||
{
|
||||
throw OutOfMemory(registers.A, registers.B);
|
||||
}
|
||||
|
||||
for(unsigned i = registers.A; i < end; ++i)
|
||||
{
|
||||
std::putc(memory[i], stdout);
|
||||
@@ -29,7 +35,49 @@ namespace Execute
|
||||
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||
{
|
||||
registers.A = std::getchar();
|
||||
if (registers.A == '\n')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while(std::getchar() != '\n');
|
||||
},
|
||||
// 11 get string from STDIN
|
||||
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||
{
|
||||
if (registers.B <= 0)
|
||||
{
|
||||
registers.B = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (registers.A < 0 || static_cast<unsigned>(registers.A + registers.B) >= memory.size())
|
||||
{
|
||||
throw OutOfMemory(registers.A, registers.B);
|
||||
}
|
||||
|
||||
int charactersRead = 0;
|
||||
bool newlineRead = false;
|
||||
while(charactersRead < registers.B)
|
||||
{
|
||||
char result = std::getchar();
|
||||
if (result == '\n')
|
||||
{
|
||||
newlineRead = true;
|
||||
break;
|
||||
}
|
||||
|
||||
memory[registers.A + charactersRead] = result;
|
||||
++charactersRead;
|
||||
}
|
||||
|
||||
registers.B = charactersRead;
|
||||
|
||||
if (!newlineRead)
|
||||
{
|
||||
while(std::getchar() != '\n');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user