My problem is getting a 64-bit key from user. For this I need to get 16 characters as string which contains hexadecimal characters (123456789ABCDEF). I got the string from user and I reached characters with the code below. But I don't know how to convert character to 4-bit binary
.data
insert_into:
.word 8
Ask_Input:
.asciiz "Please Enter a Key which size is 16, and use hex characters : "
key_array:
.space 64
.text
.globl main
main:
la $a0, Ask_Input
li $v0, 4
syscall
la $a0, insert_into
la $a1, 64
li $v0, 8
syscall
la $t0, insert_into
li $t2, 0
li $t3, 0
loop_convert:
lb $t1, ($t0)
addi $t0, $t0, 1
beq $t1, 10, end_convert
# Now charcter is in $t1 but
#I dont开发者_如何学编程 know how to convert it to 4 bit binary and storing it
b loop_convert
end_convert:
li $v0, 10 # exit
syscall
I don't think masking with 0x15 as @Joelmob's opinion is the right solution, because
'A' = 0x41 → 0x41 & 0x15 = 0
'B' = 0x42 → 0x42 & 0x15 = 0
'C' = 0x43 → 0x43 & 0x15 = 1
'D' = 0x44 → 0x44 & 0x15 = 4
'E' = 0x45 → 0x45 & 0x15 = 5
'F' = 0x46 → 0x46 & 0x15 = 4
which doesn't produce any relevant binary values
The easiest way is subtracting the range's lower limit from the character value. I'll give the idea in C, you can easily convert it to MIPS asm
if ('0' <= ch && ch <= '9')
{
return ch - '0';
}
else if ('A' <= ch && ch <= 'F')
{
return ch - 'A' + 10;
}
else if ('a' <= ch && ch <= 'f')
{
return ch - 'a' + 10;
}
Another way to implement:
if ('0' <= ch && ch <= '9')
{
return ch & 0x0f;
}
else if (('A' <= ch && ch <= 'F') || ('a' <= ch && ch <= 'f'))
{
return (ch & 0x0f) + 9;
}
However this can be further optimized to a single comparison using the technique describes in the following questions
- Fastest way to determine if an integer is between two integers (inclusive) with known sets of values
- Check if number is in range on 8051
Now the checks can be rewritten as below
if ((unsigned char)(ch - '0') <= ('9'-'0'))
if ((unsigned char)(ch - 'A') <= ('F'-'A'))
if ((unsigned char)(ch - 'a') <= ('f'-'a'))
Any modern compilers can do this kind of optimization, here is an example output
hex2(unsigned char):
andi $4,$4,0x00ff # ch, ch
addiu $2,$4,-48 # tmp203, ch,
sltu $2,$2,10 # tmp204, tmp203,
bne $2,$0,$L13
nop
andi $2,$4,0xdf # tmp206, ch,
addiu $2,$2,-65 # tmp210, tmp206,
sltu $2,$2,6 # tmp211, tmp210,
beq $2,$0,$L12 #, tmp211,,
andi $4,$4,0xf # tmp212, ch,
j $31
addiu $2,$4,9 # D.2099, tmp212,
$L12:
j $31
li $2,255 # 0xff # D.2099,
$L13:
j $31
andi $2,$4,0xf # D.2099, ch,
Have a look at this ASCII table you will see that hex-code for numbers from 9 and below are 0x9 and for capital letters this is between 0x41 and 0x5A A-Z determine if its a number or character, you see if theres a number its quite done, if it were a character mask with 0x15 to get the four bits.
If you want to include lowercase letters do same procedure with masking and determine if its a char between 0x61 and 0x7A
精彩评论