From 61ba182b13926331c76fc4f4e2ba9877f85876f5 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Sat, 27 May 2017 19:19:13 +0200 Subject: [PATCH] Aggiunte a documentazione --- INSTRUCTION_SET.md => IMPLEMENTATION.md | 168 ++++++++++++++---------- README.md | 4 +- res/functions.png | Bin 0 -> 22426 bytes 3 files changed, 100 insertions(+), 72 deletions(-) rename INSTRUCTION_SET.md => IMPLEMENTATION.md (62%) create mode 100644 res/functions.png diff --git a/INSTRUCTION_SET.md b/IMPLEMENTATION.md similarity index 62% rename from INSTRUCTION_SET.md rename to IMPLEMENTATION.md index 9f9e8ed..5d1d962 100644 --- a/INSTRUCTION_SET.md +++ b/IMPLEMENTATION.md @@ -22,6 +22,33 @@ for i, o in enumerate(ops): o.set_value(arr[i]) ``` +# Assembling, labels and functions + +The enclosed assembler recognizes **labels** and **functions**. The **main** function has to be defined. Here is an example: + +``` +def foo: +addi r0, 0x3 +movi r1, 0x1 +retn + +def main: # main is mandatory +movi r0, 0xff +nope +jmpi label # jumping to label +nope +addi r0, 0x2 +label: # defining a label +grmn +call foo +shit +``` +In order to jump to a label or a function, an *immediate type* jump has to be used (`JMPI, JPBI, JPAI`, etc...). The `CALL` instruction is used to save where the program has to restore its execution after a function call. + +The assembler puts the **main** function as first in the code section meaning its code will be located at offset 0. Every other function will follow. + +![Functions] + # Instruction set The instruction set I come out wants to be "RISC"-oriented but I have to admit that it is more "CISC"-oriented *(Confusing Instruction Set Computer)*. Also, since I decided that every instruction had to be 4 chars long, some name adaptation may have encountered some quality issue... (yes, `POP`, I'm looking at you) @@ -96,141 +123,141 @@ Effect: R1 is decremented by R0 ``` ## ANDB ``` -Full name: -Usage: -Effect: +Full name: AND Byte (immediate) +Usage: ANDB R0, 0xFF +Effect: R0's lower byte is and-ed by 0xFF. ``` ## ANDW ``` -Full name: -Usage: -Effect: +Full name: AND Word (immediate) +Usage: ANDW R0, 0xFFFF +Effect: R0's is and-ed by 0xFFFF. ``` ## ANDR ``` -Full name: -Usage: -Effect: +Full name: AND Register +Usage: ANDR R0, R1 +Effect: R0 is and-ed by R1. ``` ## YORB ``` -Full name: -Usage: -Effect: +Full name: (Y)OR Byte (immediate) +Usage: YORB R0, 0xFF +Effect: R0's lower byte is or-ed by 0xFF. ``` ## YORW ``` -Full name: -Usage: -Effect: +Full name: (Y)OR Word (immediate) +Usage: YORW R0, 0xFFFF +Effect: R0's is or-ed by 0xFFFF. ``` ## YORR ``` -Full name: -Usage: -Effect: +Full name: (Y)OR Register +Usage: YORR R0, R1 +Effect: R0 is or-ed by R1. ``` ## XORB ``` -Full name: -Usage: -Effect: +Full name: XOR Byte (immediate) +Usage: XORB R0, 0xFF +Effect: R0's lower byte is xor-ed by 0xFF. ``` ## XORW ``` -Full name: -Usage: -Effect: +Full name: XOR Word (immediate) +Usage: XORW R0, 0xFFFF +Effect: R0 is xor-ed by 0xFFFF. ``` ## XORR ``` -Full name: -Usage: -Effect: +Full name: XOR Register +Usage: XORR R0, R1 +Effect: R0 is xor-ed by R1. ``` ## NOTR ``` -Full name: -Usage: -Effect: +Full name: NOT Register +Usage: NOTR R0 +Effect: Bitwise negation of R0. ``` ## MULI ``` -Full name: -Usage: -Effect: +Full name: MULtiply by Immediate +Usage: MULI R0, 2 +Effect: R0 is multiplied by 2. ``` ## MULR ``` -Full name: -Usage: -Effect: +Full name: MULtiply by Register +Usage: MULR R0, R1 +Effect: R0 is multiplied by R1. ``` ## DIVI ``` -Full name: -Usage: -Effect: +Full name: DIVide by Immediate +Usage: DIVI R0, 2 +Effect: R0 is divided by 2. The remainder is not stored. ``` ## DIVR ``` -Full name: -Usage: -Effect: +Full name: DIVide by Register +Usage: DIVR R0, R1 +Effect: R0 is divided by R1. The remainder is not stored. ``` ## SHLI ``` -Full name: -Usage: -Effect: +Full name: SHift Left by Immediate +Usage: SHLI R0, 2 +Effect: Effect: R0 is shifted 2 bits to the left. ``` ## SHLR ``` -Full name: -Usage: -Effect: +Full name: SHift Left by Register +Usage: SHLR R0, R1 +Effect: R0 is shifted R1 bits to the left. ``` ## SHRI ``` -Full name: -Usage: -Effect: +Full name: SHift Right by Immediate +Usage: SHRI R0, 2 +Effect: Effect: R0 is shifted 2 bits to the right. ``` ## SHRR ``` -Full name: -Usage: -Effect: +Full name: SHift Right by Register +Usage: SHRR R0, R1 +Effect: R0 is shifted R1 bits to the right. ``` ## PUSH ``` -Full name: -Usage: -Effect: +Full name: PUSH +Usage: PUSH R1 +Effect: Pushes R1 on top of the stack. ``` ## POOP ``` -Full name: -Usage: -Effect: +Full name: POP (+ 1 free 'O') +Usage: POOP R1 +Effect: Retrieves the element on top of the stack and puts it in R1. ``` ## CMPB ``` -Full name: -Usage: -Effect: +Full name: CoMPare register to Byte +Usage: CMPB R0, 0xff +Effect: Compares R0 to 0xFF (R0's lower byte) and sets the ZF and CF flags. ``` ## CMPW ``` -Full name: -Usage: -Effect: +Full name: CoMPare register to Word +Usage: CMPW R0, 0xffff +Effect: Compares R0 to 0xFFFF and sets the ZF and CF flags. ``` ## CMPR ``` -Full name: -Usage: -Effect: +Full name: CoMPare register to Register +Usage: CMPR R0, R1 +Effect: Compares R0 to R1 and sets the ZF and CF flags. ``` ## JMPI ``` @@ -320,7 +347,7 @@ Effect: Does nothing for an instruction ``` Full name: GeRMaNo Usage: GRMN -Effect: Sets every register (excluding IP and RP) to GG +Effect: Sets every register (excluding IP and RP) to GG (0x4747) ``` ## DEBG ``` @@ -331,3 +358,4 @@ Effect: Prints the status of every register and the flags [Instruction]: ./res/instruction.png [Structure]: ./res/structure.png +[Functions]: ./res/functions.png diff --git a/README.md b/README.md index 13fbc11..356f1da 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The design and the implementation behind Pasticciotto are not state-of-the-art b I do not want to spoil the challenge for those that haven't completed it yet. Check out some write-up online! # Instruction set -Check out the file [INSTRUCTION_SET.MD](IS) to understand how the VM works and which operations it can do! Watch out for some spoilers if you haven't completed the challenge though! +Check out the file [IMPLEMENTATION.MD](IMPL) to understand how the VM works and which operations it can do! Watch out for some spoilers if you haven't completed the challenge though! # Why "Pasticciotto"? In Italian, "Pasticciotto" has two meanings! @@ -44,4 +44,4 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR DEALINGS IN THE SOFTWARE. ``` [Pasticciotto]: ./res/pasticciotto.png -[IS]: ./INSTRUCTION_SET.md \ No newline at end of file +[IMPL]: ./IMPLEMENTATION.md \ No newline at end of file diff --git a/res/functions.png b/res/functions.png new file mode 100644 index 0000000000000000000000000000000000000000..c4ca72874525ae7d605be9c77aecb9548d9cba7d GIT binary patch literal 22426 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 r;`{JH53-Vp~p?z5pK@%Wc0_whr!YKLDbbF``w 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 O_;~)&<14p_WB&m