AB6 Low-Level Programming

Implement the following functions using only the already imported functions. Additionally, the following language constructs are not permitted:

Part 1: Counter Machines

A counter machine consists of multiple registers. Each register can hold an integer ≥ 0. The value in each register can be incremented or decremented by one. If a register contains a 0 and is decremented then it still contains a 0 afterwards. Additionally, it can be checked whether the number contained in a register is 0. The following functions are available to control a counter machine.
inc    :: CM -> Int -> CM
dec    :: CM -> Int -> CM 
isZero :: CM -> Int -> Bool
The function inc (dec) increments (decrements) register arg2 by one. The first register is 1.
The function isZero returns true iff the register arg2 contains 0.
move :: CM -> CM
copy :: CM -> CM
add  :: CM -> CM
mult :: CM -> CM
For a counter machine with \(k\) registers let \(R_i\) and \(R_i'\) denote the integers contained in register \(i\) at the beginning of the computation and at the end, respectively, for all \( 1 \leq i \leq k \).
The function move moves the value in the first register to the second for a counter machine with 2 registers, i.e. \(R_2' = R_1\).
The function copy copies the value in the first register to the second for a counter machine with 3 registers, i.e. \(R_1' = R_2' = R_1\).
The function add adds the value in the first and second register and writes the result to the third register for a counter machine with 3 registers, i.e. \(R_3' = R_1 + R_2\).
The function mult multiplies the value in the first and second register and writes the result to the third register for a counter machine with 4 registers, i.e. \(R_3' = R_1 \cdot R_2\).
Examples ('_' denotes an arbitrary number):

Part 2: Stack Machine

A stack machine is a generalization of counter machines where the registers contain strings instead of integers. A stack machine has the following operations and predicates. The last character of a string in a register can be removed. A character can be appended to the end of a string in a register. It can be checked whether the string in a register is empty or whether its last character equals a certain character. The following functions are available to control a stack machine.
push    :: SM -> Int -> Char -> SM
pop     :: SM -> Int -> SM
isEmpty :: SM -> Int -> Bool
isChar  :: SM -> Int -> Char -> Bool
The function push appends the character arg3 to the string in register arg2.
The function pop removes the last character from the string in register arg2 (the string remains unchanged if it is empty).
The function isEmpty returns true iff the string in register arg2 is empty.
The function isChar returns true iff the last character of the string in register arg2 equals arg3.
reverse :: SM -> SM
move    :: SM -> SM
copy    :: SM -> SM
concat  :: SM -> SM
substr  :: SM -> SM
For a stack machine with \(k\) registers let \(R_i\) and \(R_i'\) denote the string contained in register \(i\) at the beginning of the computation and at the end, respectively, for all \( 1 \leq i \leq k \).
The function reverse writes the string contained in register 1 in reverse order to register 2 for a stack machine with 2 registers, i.e. \(R_2' = \text{reverse}(R_1)\).
The function move moves the string in register 1 to register 2 for a stack machine with 3 registers, i.e. \(R_2' = R_1\).
The function copy copies the string in register 1 to register 2 for a stack machine with 3 registers, i.e. \(R_1' = R_2' = R_1\).
The function concat appends the string in register 2 to the string in register 1 and writes the resulting string to register 3 for a stack machine with 3 registers, i.e. \(R_3' = R_1 R_2\).
The function substr writes the substring of \(R_1\) which starts from the \((|R_2|+1)\)-th character and has length \(|R_3|\) to register 4.
You may assume that strings in the stack machine only consist of the characters 'a','b','c'. Examples: