The "Prolog" way would be to actually maintain the state of all your registers in a term which you pass along the main predicate that runs the simulation. So, for example:
% general-purpose registers
% regs(EAX, EBX, ECX, EDX, ESI, EDI)
regs(0, 0, 0, 0, 0, 0)
But please note: this is not a predicate (hence the missing dot at the end)! This is a term, and it will be initialized to all zeros (I am assuming here):
init_regs(regs(0,0,0,0,0,0)).
So at the beginning of your program you can initialize your registers with:
main :-
init_regs(Regs),
step(Regs).
step(Regs) :-
read_instruction(Instruction),
apply_instruction(Instruction, Regs, New_regs),
step(New_regs).
apply_instruction(add(eax, Addend),
regs(EAX, EBX, ECX, EDX, ESI, EDI),
regs(New_EAX, EBX, ECX, EDX, ESI, EDI)) :-
New_EAX is EAX + Addend.
You can leave it at this, or you can have a helper predicate that provides access to the one register you need, for example:
reg_eax(reg(EAX, _, _, _, _, _), EAX).
reg_ebx(reg(_, EBX, _, _, _, _), EBX).
% and so on
And to set a register:
set_reg_eax(reg(EAX, EBX, ECX, EDX, ESI, EDI),
New_EAX,
reg(New_EAX, EBX, ECX, EDX, ESI, EDI)).
% and so on
which you can then use like this to define your apply_instruction/3
:
apply_instruction(add(eax, Addend), Regs, New_regs) :-
reg_eax(Regs, EAX),
New_EAX is EAX + Addend,
set_reg_eax(Regs, New_EAX, New_regs).
The sort of predicates, reg_eax
and set_reg_eax
can be automatically generated by a library, library(record)
(see here), with the initial idea proposed by Richard o'Keefe in his book "The Craft of Prolog" for doing exaclty this sort of stuff. If you use the libary, you don't need to write all the access and set predicates yourself.
If you are using SWI-Prolog, however, you can also make use of Dicts
; see here. This is part of the current development version of SWI-Prolog (version 7) and makes dealing with structures with named arguments much easier.