From fc2870ca74715db896f9e2181029d6207ef5fbb5 Mon Sep 17 00:00:00 2001 From: Tijmen van Nesselrooij Date: Sun, 17 May 2020 14:13:15 +0200 Subject: [PATCH] Add string input interrupt from STDIN --- README.md | 31 ++++++++++++----------- bin/test.wasm | 12 ++++++++- include/execute/error.hpp | 6 +++++ src/execute/error.cpp | 9 +++++++ src/execute/interrupts.cpp | 50 +++++++++++++++++++++++++++++++++++++- 5 files changed, 92 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index fde18dd..695d862 100644 --- a/README.md +++ b/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` get a single ASCII character from STDIN and store it in register A \ No newline at end of file +- [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. \ No newline at end of file diff --git a/bin/test.wasm b/bin/test.wasm index 1e6ed42..eba9ae1 100644 --- a/bin/test.wasm +++ b/bin/test.wasm @@ -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: diff --git a/include/execute/error.hpp b/include/execute/error.hpp index 590358c..8325da4 100644 --- a/include/execute/error.hpp +++ b/include/execute/error.hpp @@ -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 diff --git a/src/execute/error.cpp b/src/execute/error.cpp index 5c39726..4781bc0 100644 --- a/src/execute/error.cpp +++ b/src/execute/error.cpp @@ -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() diff --git a/src/execute/interrupts.cpp b/src/execute/interrupts.cpp index 867fed9..a996b10 100644 --- a/src/execute/interrupts.cpp +++ b/src/execute/interrupts.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace Execute @@ -18,6 +19,11 @@ namespace Execute [](Execute::Registers & registers, std::vector & 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 & memory) { registers.A = std::getchar(); - } + if (registers.A == '\n') + { + return; + } + + while(std::getchar() != '\n'); + }, + // 11 get string from STDIN + [](Execute::Registers & registers, std::vector & memory) + { + if (registers.B <= 0) + { + registers.B = 0; + return; + } + + if (registers.A < 0 || static_cast(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'); + } + }, }; } } \ No newline at end of file