Write a rule to handle the store instruction.
You may use any of the "helper" functions listed (you do not need to write them).
Be sure to describe the expected output/behaviour of your test case.
% run(M,R)
% --------
% run a Marie program where M is a list representing the
% contents of memory at the start of the program,
% and R is a list representing some of the register contents
% in order [ ACC, PC, IR ]
%
% the contents of each register and each memory cell is
% represented using a string of 4 hex digits
% e.g. M = [ "5000", "2005", "3005", "6000", "7000", "0003" ]
run(M,R) :-
fetch(M,R,R1), % R1 contains the register values after the fetch/decode
execute(M,R1,R2,M2), % R2 and M2 are the register/memory contents after execution
!, (testforhalt(R2) % quit if the instruction was halt,
; run(M2,R2)). % otherwise continue execution with new M and R
% fetch(M,R,Rnew)
% ---------------
% fetch the next instruction from memory,
% using the PC (second element of R) to identify the correct element of M
% the contents of Rnew will be the same as R except as follows:
% the IR element should contain the newly fetched instruction
% the PC element should be greater by 1
fetch(M,[Acc, PC, _] , [Acc, NewPC, NewIR] ) :-
int2hexstr(Addr, PC), % convert the PC string to an integer address
nth0(Addr, M, NewIR), % look up the instruction
NewAddr is Addr + 1, % calculate the next instruction address
int2hexstr(NewAddr, NewPC). % convert the integer address back to a string
% execute(M,R,Rnew,Mnew)
% ----------------------
% M,R represent the current memory and register lists,
% identify the instruction (the IR element of R), then
% compute/set the updated register and memory lists
% execute the halt instruction: nothing changes, just succeed
execute(_, [_, _, "7000"], _, _).
% execute the output instruction: no content changes,
% but the contents of Acc are displayed
execute(M, [Acc, PC, "6000"] , [Acc, PC, "6000"], M) :-
format("~w~n", [Acc]).
% execute the input instruction: the contents of Acc are updated by a read
execute(M, [_, PC, "5000"] , [NewAcc, PC, "5000"], M) :-
format("Enter a value followed by a period, e.g. 32.~n"),
read(NewAcc).
% execute the add instruction: the contents of the Acc are updated\
execute(M, [Acc, PC, IR], [NewAcc, PC, IR], M) :-
instrMatch("2000", IR), % make sure the first char of instruction is "2"
extractArg(IR, "2000", MemAddr), % get the memory address from the instruction
lookupMemVal(MemAddr, M, MemVal), % get the int val from memory address
int2hexstr(AccVal, Acc), % get the value from Acc as an integer
NewAccVal is AccVal + MemVal, % compute int value for new Acc
int2hexstr(NewAccVal, NewAcc). % convert to string for register
% ---------- Descriptions of available helper functions ------------------
% testforhalt(R)
% succeeds iff the IR element of R is the halt instruction
testforhalt( [_, "7000" | _] ).
% lookupMemVal(Addr, Mem, Val)
% given an address in memory, lookup the value stored there as an integer
% extractArg(InstrStr, BaseStr, IntArg)
% given a hex string, InstrStr, representing an instruction, (e.g. "2005")
% and a base string, BaseStr, representing the instruction type (e.g. "2000")
% extract the argument portion as an integer (e.g. 5)
% int2hexstr(I,HS)
% converts between an integer value I and a hex string HS
% instrMatch(Base,HS)
% succeeds if first char of Base matches first char of string HS
% testCase(N)
% run the simulator on a numbered test case
% test case 1: read a number, output, add 3 (from mem addr 5), output, halt
testCase(1) :- M = [ "5000", "6000", "2005", "6000", "7000", "0003" ],
R = [ "0000", "0000", "0000" ],
run(M,R).
|
| wxyz | f |
| 0000 | |
| 0001 | |
| 0010 | 0 |
| 0011 | |
| 0100 | |
| 0101 | |
| 0110 | |
| 0111 | |
| 1000 | |
| 1001 | |
| 1010 | 1 |
| 1011 | |
| 1100 | |
| 1101 | |
| 1110 | |
| 1111 |
Top, input
store X
skipcond 000
jump Done
add Y
store Y
jump Top
Done, load Y
output
halt
X, dec 0
Y, dec 0
|
(defun f (L)
(cond
((not (listp L)) nil)
((null L) nil)
((not (numberp (car L))) (f (cdr L)))
(t (cons (car L) (f (cdr L))))))
|