How can I print an array in Mips64? I've succeeded in printing the array in QtSPIM (MIPS32), with this code:
.data
array: .word 10 20 30 40 50
.text
#load base address of array
la $t1,array
#load number of elements
ld $t2,num
loop:
#load word
lw $a0, ($t1)
#print element
li $v0,1
syscall
#print space
la $a0, space
li $v0,4
syscall
addi $t1,4
#increase counter
addi $t0, 1
bne $t0,$t2,loop
#end
li $v0,10
syscall
I know that MIPS64 has daddi instead of addi but I am still missing something.
WinMips64 doesn't appear to use syscall for terminal output like SPIM / MARS, but rather implements it using memory-mapped I/O (see this example code).
The CONTROL port is located at address 0x10000, and the DATA port at address 0x10008.
Since you're printing integers you'll be interested mainly in these two output modes:
; Set CONTROL = 1, Set DATA to Unsigned Integer to be output
; Set CONTROL = 2, Set DATA to Signed Integer to be output
For example:
ori $a1,$0,0
lui $a1,1 ; $a1 = 0x10000 (CONTROL)
ori $a2,$a1,8 ; $a2 = 0x10008 (DATA)
lwu $a0,($t1) ; load an unsigned 32-bit value
ori $v0,$0,1 ; 1 == print unsigned integer
sd $a0, ($a2) ; set value to print
sd $v0, ($a1) ; ..and write the command to print it
Related
Can you please explain to me what aL, aH, bL, bH stands for
aL = a low byte
aH = a high byte
bL = b low byte
bH = b high byte
In this case a is the minimum serial number count value and b is the maximum serial number count value.
I would want to ask, how do you break up a 32-bit hex (for example: CEED6644) into 4 bytes (var1 = CE, var2 = ED, var3 = 66, var4 = 44). In QB64 or QBasic. I would use this to store several data bytes into one array address.
Something like this:
DIM Array(&HFFFF&) AS _UNSIGNED LONG
Array(&HAA00&) = &HCEED6644&
addr = &HAA00&
SUB PrintChar
SHARED addr
IF var1 = &HAA& THEN PRINT "A"
IF var1 = &HBB& THEN PRINT "B"
IF var1 = &HCC& THEN PRINT "C"
IF var1 = &HDD& THEN PRINT "D"
IF var1 = &HEE& THEN PRINT "E"
IF var1 = &HFF& THEN PRINT "F"
IF var1 = &H00& THEN PRINT "G"
IF var1 = &H11& THEN PRINT "H"
And so on...
You could use integer division (\) and bitwise AND (AND) to accomplish this.
DIM x(0 TO 3) AS _UNSIGNED _BYTE
a& = &HCEED6644&
x(0) = (a& AND &HFF000000&) \ 2^24
x(1) = (a& AND &H00FF0000&) \ 2^16
x(2) = (a& AND &H0000FF00&) \ 2^8
x(3) = a& AND &HFF&
PRINT HEX$(x(0)); HEX$(x(1)); HEX$(x(2)); HEX$(x(3))
Note that you could alternatively use a generic RShift~& function instead of raw integer division since what you're really doing is shifting bits:
x(0) = RShift~&(a& AND &HFF000000&, 18)
...
FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED BYTE)
' Raise illegal function call if the shift count is greater than the width of the type.
' If shiftCount is not _UNSIGNED, then you must also check that it isn't less than 0.
IF shiftCount > 32 THEN ERROR 5
RShift~& = value / 2^shiftCount
END FUNCTION
Building upon that, you might create another function:
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value AND LShift~&(&HFF&, 8*position), 8*position)
END FUNCTION
Note that an LShift~& function was used that shifts bits to the left (multiplication by a power of 2). A potentially better alternative would be to perform the right-shift first and just mask the lower 8 bits, eliminating the need for LShift~&:
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION
Incidentally, another QB-like implementation known as FreeBASIC has an actual SHR operator, used like MOD or AND, to perform a shift operation directly instead of using division, which is potentially faster.
You could also use QB64's DECLARE LIBRARY facility to create functions in C++ that will perform the shift operations:
/*
* Place in a separate "shift.h" file or something.
*/
unsigned int LShift (unsigned int n, unsigned char count)
{
return n << count;
}
unsigned int RShift (unsigned int n, unsigned char count)
{
return n >> count;
}
Here's the full corresponding QB64 code:
DECLARE LIBRARY "shift"
FUNCTION LShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
END DECLARE
x(0) = ByteAt~%%(a&, 0)
x(1) = ByteAt~%%(a&, 1)
x(2) = ByteAt~%%(a&, 2)
x(3) = ByteAt~%%(a&, 3)
END
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION
If QB64 had a documented API, it might be possible to raise a QB64 error from the C++ code when the shift count is too high, rather than relying on the behavior of C++ to essentially ignore shift counts that are too high. Unfortunately, this isn't the case, and it might actually cause more problems than it's worth.
This snip gets the byte pairs of a hexidecimal value:
DIM Value AS _UNSIGNED LONG
Value = &HCEED6644&
S$ = RIGHT$("00000000" + HEX$(Value), 8)
PRINT "Byte#1: "; MID$(S$, 1, 2)
PRINT "Byte#2: "; MID$(S$, 3, 2)
PRINT "Byte#3: "; MID$(S$, 5, 2)
PRINT "Byte#4: "; MID$(S$, 7, 2)
I have a Lua string like "382+323" or "32x291" or "94-23", how can I check and return the position of the operands?
I found String.find(s, "[+x-]") did not work. Any ideas?
th> str = '5+3'
th> string.find(str, '[+-x]')
1 1
th> string.find(str, '[+x-]')
2 2
[+-x] is a pattern match for 1 character in the range between "+" and "x".
When you want to use dash as character and not as the meta character you should start or end the character group with it.
print("Type an arithmetic expression, such as 382 x 3 / 15")
expr = io.read()
i = -1
while i do
-- Find the next operator, starting from the position of the previous one.
-- The signals + and - are special characters,
-- so you have to use the % char to escape each one.
-- [The find function returns the indices of s where this occurrence starts and ends][1].
-- Here we are obtaining just the start index.
i = expr:find("[%+x%-/]", i+1)
if i then
print("Operator", expr:sub(i, i), "at position", i)
end
end
I am using Lua on Redis and want to compare two signed 64-bit numbers, which are stored in two 8-byte/character strings.
How can I compare them using the libraries available in Redis?
http://redis.io/commands/EVAL#available-libraries
I'd like to know >/< and == checks. I think this probably involves pulling two 32-bit numbers for each 64-bit int, and doing some clever math on those, but I am not sure.
I have some code to make this less abstract. a0, a1, b0, b1 are all 32 bit numbers used to represent the msb & lsb's of two 64-bit signed int 64s:
-- ...
local comp_int64s = function (a0, a1, b0, b1)
local cmpres = 0
-- TOOD: Real comparison
return cmpres
end
local l, a0, a1, b0, b1
a0, l = bit.tobit(struct.unpack("I4", ARGV[1]))
a1, l = bit.tobit(struct.unpack("I4", ARGV[1], 5))
b0, l = bit.tobit(struct.unpack("I4", blob))
b1, l = bit.tobit(struct.unpack("I4", blob, 5))
print("Cmp result", comp_int64s(a0, a1, b0, b1))
EDIT: Added code
I came up with a method that looks like it's working. It's a little ugly though.
The first step is to compare top 32 bits as 2 compliment #’s
MSB sign bit stays, so numbers keep correct relations
-1 —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647
So returning the result from the MSB's works unless they are equal, then the LSB's need to get checked.
I have a few cases to establish the some patterns:
-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD
And
8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD
The sign bit on MSB’s doesn’t matter b/c negative numbers have the same relationship between themselves as positive numbers. e.g regardless of sign bit, lsb values of 0xff > 0xfe, always.
What about if the MSB on the lower 32 bits is different?
0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!
So we need to ignore the sign bit on the lower 32 bits. And since the relationships are the same for the LSBs regardless of sign, just using
the lowest 32 bits unsigned works for all cases.
This means I want signed for the MSB's and unsigned for the LSBs - so chaging I4 to i4 for the LSBs. Also making big endian official and using '>' on the struct.unpack calls:
-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
if as0 > bs0 then
return 1
elseif as0 < bs0 then
return -1
else
-- msb's equal comparing lsbs - these are unsigned
if au1 > bu1 then
return 1
elseif au1 < bu1 then
return -1
else
return 0
end
end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))
Comparing is a simple string compare s1 == s2.
Greater than is when not s1 == s2 and i1 < i2.
Less than is the real work. string.byte allows to get single bytes as unsigned char. In case of unsigned integer, you would just have to check bytes-downwards: b1==b2 -> check next byte; through all bytes -> false (equal); b1>b2 -> false (greater than); b1<b2 -> true. Signed requires more steps: first check the sign bit (uppermost byte >127). If sign 1 is set but not sign 2, integer 1 is negative but not integer 2 -> true. The opposite would obviously result in false. When both signs are equal, you can do the unsigned processing.
When you can pack more bytes to an integer, it's fine too, but you have to adjust the sign bit check. When you have LuaJIT, you can use the ffi library to cast your string into a byte array into an int64.
I'm new to MIPS and while I sort of understand how to do basic tasks with it, I'm struggling heavily with procedures/functions.
I was hoping someone could explain how to solve a simple CPP program such as
void swap( int & a, int & b )
{
register int t;
t = a; a = b; b = t;
}
Into MIPS.
In class we talked about frame pointers and stack pointers, offsets, and I'm just lost. How do you pass int a, and int b to the function? How do you return a value and use it in MIPS? I've seen similar problems with arrays but was hoping if someone could help me with one with just two ints to be swapped. Thanks.
First, you should not use the keyword register in C++, as it is deprecated and in most cases as meaningful as whitespace.
How do you pass int a, and int b to the function?
You store a and b in the registers you will use in your subroutine.
If you want to swap two values in an array, let's say at 0x80080000:
lui $t0, 0x8008 ;$t0 = 0x80080000
lw $t1 0($t0) ;load (0x80080000) in $t1
lw $t2 4($t0) ;load (0x80080004) in $t2
sw $t1 4($t0) ;store $t1 in 0x80080004
sw $t2 0($t0) ;store $t2 in 0x80080000
If you want to swap the values of two registers (xor swap algorithm):
xor $t0, $t0, $t1
xor $t1, $t0, $t1
xor $t0, $t0, $t1
Or, if you care about readability:
add $t2, $r0, $t0
add $t0, $r0, $t1
add $t1, $r0, $t2
You can create a function that do swap.
Something like that :
swap: # Swap function
addi $sp,$sp,-4
sw $t0, 0($sp) # Stack[0] = $t0
add $t0,$a0,$zero # $t0 = $a0
add $a0,$a1,$zero # $a0 = $a1
add $a1,$t0,$zero # $a1 = $t0 (swapping $a0 and $a1)
lw $t0,0($sp)
addi $sp,$sp,4 # $t0 = Stack[0]
jr $ra # Return to the code
And use the function Swap, like this:
li $a0,100 # $a0 = 100
li $a1,33 # $a1 = 33
jal swap # Swapping $a0 & $a1
Note: The names of the registers aren't important, you can use other.