How to simulate "add eax, 1" in Prolog? - prolog

I am trying to simulate some simple asm code using Prolog. (32 bit)
I am new in Prolog and I am stucked in some problems without any solutions.
Basically if here is the code:
...
add eax, 1
...
and I want to simulate in this way:
...
EAX is EAX - 1,
...
and swipl will generate errors like :
Call: (7) 1 is 1-1 ? creep
Fail: (7) 1 is 1-1 ? creep
....
false
I know basically I could do like this:
EAX_temp is EAX + 1
But how can I keep manipulate EAX in next instructions..?
Could any one give me some help..? Thank you!

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.

There are probably several good ways to do this. And the answer might further be refined by your context which is currently not clear.
One way, is you could create dynamic facts for register values:
:- dynamic(register/2). % Fill in as needed
register(eax, 0).
register(ebx, 0).
...
add(Reg, Value) :-
( retract(register(Reg, OldValue))
-> NewValue is OldValue + Value
; NewValue = Value % If the register wasn't defined
),
assertz(register(Reg, NewValue)).
Then do:
add(eax, 4). % add eax,4
To read a register, you would just use, for example:
register(eax, EAXValue).
The main drawback of assert and retract is that they take a lot more CPU time than list manipulation. But I think they make sense for this kind of application where you have a CPU "state" that is represented by several register values.

Related

How do I make this LC-3 code to count the number of 0s in the value stored in R0 and stores the result into R1

How do I modify this LC-3 code to make it count the number of 0s instead of ones
.ORIG x3000
LD R2, INPUT
AND R0, R0, #0 ; COUNTER INITIALIZED TO ZERO
ADD R1, R0, #1
ADD R3, R0, #15
LOOP
AND R4, R2, R1
BRz SKIP
ADD R0, R0, #1
SKIP
ADD R1, R1, R1
ADD R3, R3, #-1
BRzp LOOP
INPUT .FILL x1997
.END
Have you watched how it works in the debugger?  Single step this small program, and you'll see how it works.
Can you find the if-then construct in here?  An if-then construct has the form if-condition-then-action.  So, you're looking for something that has this effect:
if ( bit is set )
R0++;
And you want to change it to the opposite condition, so it counts zeros instead.
if ( bit is clear )
R0++;
Where bit is clear is the same as ! (bit is set), i.e. it is the opposite.
Note that the above is in terms of structured language like C.  In assembly, if-condition-then-action looks more like this:
if ( condition is false ) goto Label1; // action is skipped if condition is false
..action.. // action runs if condition is true
Label1:
This is because the only control structure in assembly/machine code is conditional branch, which in C looks like if ( condition ) goto label;
If, i suppose, your program is OK (i don't try it) a quick modification is to flip all 0 to 1 and 1 to 0.
NOT do the job!
I leave you the exercise.
Another way, is that if you count n bit1 this mean that you have 16-n bit0...
Again NOT is your friend to compute 16-n
Note that both leave the code intact which can be used as a subroutine.
Don't forget to use HALT to stop the program

FPU first command execution

I ve this code, there we have a distance (D) and an angle (A), the functions must returns X, x=cosine(a)*d and Y, y=sine(a)*d
.data
n180 word 180
d word 60
a word 10
x word 0
y word 0
.code
fild word ptr a
fild word ptr n180
fdiv
fldpi
fmul
fsincos
fild word ptr d
fmul
fistp word ptr x
fwait
fxch
fild word ptr d
fmul
fistp word ptr y
at first time i run the program (using a=10 and d=60) i get X=59 e Y=-32768
here X is right, i get it before use FXCH but Y is wrong. if i run the program again then i get X=59 and Y=10
now it's ok
Why first time I run I get an error with FXCH?
For completeness...
... the no-operand FADD, FDIV, FDIVR, FMUL, FSUB and FSUBR all pop the right-hand argument ST(0) (so the left-hand argument ST(1) is replaced by the result, and then the stack is popped and the result becomes ST(0)).
... so the FXCH is not required.
... indeed, without the FXCH your sequence of operations leaves the FPU register stack in the same state as it started in (assuming it does not overflow at any point), which is generally a Good Thing.
I note that both FADD and FADDP etc. (with no operands) are just shorthand for FADDP ST(1), ST(0) (Intel ordering) and that is not the same as FADD ST(1), ST(0). I note also that the Intel manual prefers the FADDP etc. mnemonics for the no-operand form.

Avr assembly Y pointer

If the Y pointer stores the address of the byte in memory it points to, how is the value stored at the location accessed?
.dseg ; Define a data segment
Cap_string: .byte 5
main:
ldi yl, low(Cap_string)
ldi yh, high(Cap_string)
The instruction to read from the location that a pointer is pointing to is called "Load Indirect" and looks like this:
ld r5, Y
In the example above, r5 can probably be any register, and Y is the name of the pointer, and can be replaced with X, Y, or Z.
To write to the location, use the "Store Indirect" instruction, which is written like this:
st r5, Y
You can find more information in the AVR Instruction Set Manual.

Assembler-adding two variables

I've just tried to write my first program in assembly for x86 and I don't know why, but it doesn't make what I want. There's no errors, no communicates but the program doesn't open after pushing 'execute'. i want these program to add two variables and send back theirs sum. here's code:
.386
.model flat, stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
a dw 1h
b dw 2h
z dw 01 dup(?),0
.data?
.code
start:
mov ds, ax
mov ax, a
mov bx, b
clc
add ax, bx
mov edi, offset z
mov [edi], ax
mov ah, 09h
mov dx, z
int 21h
mov ah, 4ch
int 21h
end start
Please, help me :C
DOS function 09h expects a string; specifically, an array of bytes, each containing the ASCII code of a character, terminated by 24h (the ASCII code of $). Example:
z db '3$'
which is equivalent with:
z db 33h, 24h
Instead, you have defined z as an array of words, and fill the first word with 03h (the result of 1+2). In ASCII, 03h is a non-printing character.
Assembly is not some high-level language with convenient automatic type conversions. In assembly, you will have to convert the numeric value into a sequence of ASCII characters yourself.
How to do this? That has been asked numerous times already. Like here: Assembly, printing ascii number
Unless of course you have a convenient library with conversion functions lying around.

Prolog - Not returning desired Variable

I realised that my first question was too long and no one would understand it.
Here is the link to a condensed simpler question that exhibits my problem in a shorter program.
[Condened Question Link] Prolog - Not returning desired value
==================================================================================
I am trying to write a Brainf*ck interpreter in Prolog.
The function bf will take 3 strings. Only relevant parts of the code is as follows:
%Prog - string of BF program
%Input- string of inputs for the BF program
%Output - what the BF program will output
bf(Prog, Input,Output):- run(Prog, Input, Output).
run(Prog, Input, Output) :-
create_mem(Mem),
iterateBF(Prog,[],Mem,0, Input, Output).
%start by creating the memory space
create_mem(Memory) :-
var(Memory), %check if it is uninstantiated variable
create_mem(Memory,10000).
create_mem([],0) :- !.
create_mem([0|Tail],Size) :-
NewSize is Size - 1,
create_mem(Tail,NewSize).
%get memory value at ptr location
get_mem([Value|_],Value,0). %base case
get_mem([_|Tail],Value,Ptr) :-
Ptr > 0,
NewPtr is Ptr - 1,
get_mem(Tail,Value,NewPtr).
%for adding a value to memory space
%need to mod with 256 due to the it being 8 bits to get the actual value.
increase_mem([Value|MemTail],[NewValue|MemTail],0) :-
NewValue is (Value + 1) mod 256.
increase_mem([Head|Tail],[Head|NewTail],Ind) :-
Ind > 0,
NewInd is Ind - 1,
increase_mem(Tail,NewTail,NewInd).
%iterateBF(Prog,[],Mem,0, Input, []).
%when reach the end of the the
iterateBF([],_,_,_,_,[]) :- !.
iterateBF([],_,_,_,_,_) :-!.
iterateBF(Instruction,Inst_Iterated,Mem,Ptr,Input,Output) :-
checkInstruction(Instruction,Inst_Iterated,Mem,Ptr,Input,Output,
NewInstruction,NewInst_Iterated,NewMem,NewPtr,NewInput,NewOutput),
iterateBF(NewInstruction,NewInst_Iterated,NewMem,NewPtr,NewInput,NewOutput).
checkInstruction([Plus|ProgTail],Inst_Iterated,Mem,Ptr,Input,Output,ProgTail,Inst_Iterated,NewMem,Ptr,Input,Output) :-
char_code('+',Plus),
increase_mem(Mem,NewMem,Ptr), !.
%get the memory value at ptr
%Put into Output
checkInstruction([Period|ProgTail],Inst_Iterated,Mem,Ptr,Input,Output,ProgTail,Inst_Iterated,Mem,Ptr,Input,NewOutput) :-
char_code('.',Period),
NewOutput = [Output|Value],
get_mem(Mem,Value,Ptr),!.
The above code will compile and only work for:
bf("+.","",Out).
SWI-Prolog will just return true, while I want it to return the value of Out.
Tracing it in SWI, whenever it returns to the call of iterateBF(Prog,[],Mem,0, Input, Output) in run, Output just loses its previous value.
You just need to pay attention to the following functions:
Run
iterateBF
checkInstructions
The rest are just for compilation sake.
your checkInstruction([Plus|ProgTail],Inst_Iterated,Mem,Ptr,Input,Output,ProgTail,Inst_Iterated,NewMem,Ptr,Input,Output) it's way too complex.
And indeed your problem it's that Output doesn't get correctly bound. But instead of a 'banal' correction, what about a general improvement:
Try to comment your code, what you expect it will do, and after done, possibly simplify it as far as possible.

Resources