i wrote down this simple code just to verify the overflow in Mips Processor for my final test:
.data
.text
.globl main
main:
li $s0, 2000000000
li $s1, 2000000000
addu, $s2 , $s0, $s1
li $v0, 1
move $a0, $s2
syscall
j end
end:
li $v0, 10
syscall
it of course result in 0xee6b2800, in decimal -294967296, just because mips encode numbers in two's complement and it recognizes the MSB as the Sign bit( 1, and its negative).
How can i implement a loop for printing ( in the same program) the right value? ( In this case 4 Bil, 4x10^9)
Thank you very much
Detecting overflow is not difficult if you know both the operands and the result:
li $s0, 2000000000
li $s1, 2000000000
addu $s2 , $s0, $s1
xor $t0, $s0, $s2 # $t0 = op1 ^ result
xor $t1, $s1, $s2 # $t1 = op2 ^ result
and $t0, $t0, $t1 # $t0 = (op1 ^ result) & (op2 ^ result)
bltz $t0, overflow
Signed overflow occurs when adding two numbers of the same sign results in a number with the opposite sign.
For 32-bit numbers, if ((op1 ^ result) & 0x80000000) == 0x80000000), then op1 and result have opposite signs.
Thus, if (((op1 ^ result) & (op2 ^ result)) & 0x80000000) == 0x80000000), then that must mean that op1 and result have opposite signs, AND op2 and result also have opposite signs, therefore op1 and op2 must have the same sign. Which is exactly what we wanted to check. The bltz is just a simpler way of checking if the most significant bit (0x80000000) is set.
To print the value as an unsigned integer you probably have to write your own int-to-string conversion routine, and then print the result string using the print_string system call. That's a fairly simple operation, and you should be able to find examples if you do some searching (perhaps not for MIPS specifically, but the algorithm is the same regardless of the instruction set).
Related
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
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.
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.
I'm beginning in ARM assembly and I've been trying to write a simple integer division subroutine. So far, I have the following:
.text
start:
mov r0, #25
mov r1, #5
bl divide
b stop
divide:
cmp r0, r1
it lo
mov pc, lr
sub r0, r0, r1
add r2, r2, #1
b divide
stop:
b stop
I wrote it based on the pseudocode I came up with for the algorithm:
Is the Divisor (bottom) larger than the Dividend (top)?
Yes:
-Return the remainder and the counter(quotient)
No:
-Subtract the Divisor from the Dividend
-Increment the counter by 1
-Repeat the method
r0 contains the numerator and r1 contains the denominator.
When the algorithm finishes, r0 should contain the remainder and r2 should contain the quotient. However, upon running, r0 contains 19 and r2 contains 0.
Are there any fallacies in my logic that I'm just missing?
I removed it lo and changed mov to movlo and it worked fine.
I am building a CPU circuit with Logisim. My CPU has only 2 general purpose registers and a 16-byte RAM. I have encoded the following instruction set (Rxy means one of the two registers)
• ADD Rxy, Rxy (add Rxy and Rxy and store result inside the first register)
• SUB Rxy, Rxy (same but with sub)
• ST Rxy, Address (save value of Rxy into RAM address)
• LD Rxy, Address (load into Rxy value at RAM address)
• BZ Rxy, Address (branch to address if value of Rxy is zero)
I thought I could use decrement the second addend until it reaches 0 and at each step, add the first addend to itself.
For example, 5*3 = 5+5+5 ; 3-1-1-1
But I'm not sure my instruction can permit this program... I only have a branch if Rxy is equal to 0, whereas I would like to branch if not equal to 0.
My program currently looks like this :
Assume R1 is preloaded with second addends (iteration left count)
(A) LD R0, Address # constant 1
SUB R1, R0 # decrement iteration left
ST R1, Address # save iteration count in memory
LD R0, Address # Load first addend
LD R1, Address # load current total
ADD R0, R1 # do addition
ST R0, Address # save new current total
BZ R1, (B) # if iteration is 0, then display and end, else add
(B)
STOP
Is there a way to loop with my instruction set?
You can change
BZ R1, (B)
(B)
to
BZ R1, (B)
LD R0, Address # constant 1
SUB R0, R0
BZ R0, (A)
(B)