MIPS 使用位移运算符打印二进制小数
MIPS Using Bit Shift Operators to Print a Decimal in Binary
我在这里和其他地方在线阅读了很多关于这个主题的话题。关于移位的重要主题(不一定与汇编有关,但一般主题是:What are bitwise shift (bit-shift) operators and how do they work? I've gone as far as copying and pasting the code from the OP here: How do I print a binary number with an inputed integer? 并根据回复者的建议进行更改,无论我做什么,我都会继续生成一串零。
我明白位移是什么以及它是如何工作的。向右移动 'n' 将数字除以 2^n,向左移动将数字乘以 2^n。
上周我有一个实验,它的第三部分是提供一个程序,该程序将接受用户输入,打印出它的二进制版本,然后是十六进制版本。完成后,程序将打印出字符串中心的某些位,并生成其二进制和十六进制版本。
我最初的想法是将字符串与 0x01 相乘,打印结果“1”或“0”,然后将其右移“1”。这包含在一个循环中,并会一直持续到我的计数器满足“32”要求并完成为止。但是我对为什么它打印全是'0'感到非常困惑。我试过其他版本,例如:
将用户输入左移 31,然后对每个位执行循环,但在循环内它向右移动(以弥补位的颠倒顺序)-失败-全部又是零
与上面相反 - 再次失败,全零
我知道我想做什么,就像这样:
(NOT CODE OBVIOUSLY)
User input is: 25 <-- store at $t0
Binary rep is: 0000 0000 0000 0000 0000 0000 0001 1001 # 25 in $t0
LOOP:
AND with 0x01: 0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t1
Produces: 0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t2
Print to Console: 1 #send contents of $t2 to syscall
Shift $t0 Right 1: 0000 0000 0000 0000 0000 0000 0000 1100 #
j LOOP (until the beq branch was met and I left the loop)
我原以为这会奏效。即使它向后产生结果,我想我仍然会在我产生的字符串中收到 '1',我会注意到并相应地处理(将 $t0
中留下的整个数字移动 '31' 然后执行上面的说明。仍然全是“0”...
这是我的代码。现在,由于我的无数次尝试和更改,它又被破坏了。我只是寻求一些帮助,以了解我上面强调的方法是否完全偏离基础,以及我可以对下面的示例代码做些什么来解决这个问题。
了解到此作业已上交,但由于我的困惑而没有完成。我希望进一步了解这一点。我没有完成整个代码,因为我被这部分难住了。所以我只要求这个作业的第一部分。
#Read integer A from user and store it into a register
#Display the integer in binary
#Display the integer in Hex
#set Register $a0 to contain only bits 12,13,14,15 of $a0
#Display the integer in binary contained in $a0
#Display the integer in hex contained in $a0
.data
userInput: .asciiz "Please enter your integer:\n"
binaryInput: .asciiz "Here is the input in binary: "
nl: .asciiz "\n\n"
hexInput: .asciiz "Here is the input in hexidecmal: "
binaryOutput: .asciiz "Here is the output in binary: "
hexOutput: .asciiz "Here is the output in hexidecimal: "
.text
main:
#ask end-user to submit an integer value
li $v0, 4
la $a0, userInput
syscall
#read user-input
li $v0, 5
syscall
#enter user input into $t0
move $t0, $v0
add $t1, $zero, $zero #counter
addi $t2, $zero, 32 #target
sll $s1, $t0, 31 #shift left number 31 bits to s1
li $v0, 4
la $a0, binaryInput #print out string to user
syscall
loop:
andi $s2, $s1, 1 #and 0x01 with s1 to s2
srl $s1, $s1, 1 #shift right s1 by 1 bit
li $v0, 1
la $a0, ($s2) #print digit held in s2 to screen
syscall
add $t1, $t1, 1 #add 1 to counter
bne $t1, $t2, loop #check if counter is equal to target, if not continue loop
#exit the program
li $v0, 10
syscall
这是一种与您的基本方法有些不同的方法。它将二进制输出和十六进制输出视为通用输出函数的参数。位 masking/bit 移位类似,但掩码和位宽可变。
# Read integer A from user and store it into a register
# Display the integer in binary
# Display the integer in Hex
# set Register $a0 to contain only bits 12,13,14,15 of $a0
# Display the integer in binary contained in $a0
# Display the integer in hex contained in $a0
.data
userInput: .asciiz "Please enter your integer: "
binaryInput: .asciiz "Here is the input in binary: "
nl: .asciiz "\n"
hexInput: .asciiz "Here is the input in hexadecimal: "
binaryOutput: .asciiz "Here is the output in binary: "
hexOutput: .asciiz "Here is the output in hexadecimal: "
hexDigit: .asciiz "0123456789ABCDEF"
obuf: .space 100
obufe:
.text
.globl main
main:
# ask end-user to submit an integer value
li $v0,4
la $a0,userInput
syscall
# read user-input
li $v0,5
syscall
move $s0,$v0
# output original in binary
la $a0,binaryInput
li $a1,32
jal prtbin
# output original in hex
la $a0,hexInput
li $a1,32
jal prthex
# isolate bits 12,13,14,15
srl $s0,$s0,12
andi $s0,$s0,0x0F
# output isolated in binary
la $a0,binaryOutput
li $a1,4
jal prtbin
# output isolated in hex
la $a0,hexOutput
li $a1,4
jal prthex
# exit the program
li $v0,10
syscall
# prtbin -- print in binary
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
prtbin:
li $a2,1 # bit width of number base digit
j prtany
# prthex -- print in hex
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
prthex:
li $a2,4 # bit width of number base digit
j prtany
# prtany -- print in given number base
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
# a2 -- bit width of number base digit
# s0 -- number to print
#
# registers:
# t0 -- current digit value
# t5 -- current remaining number value
# t6 -- output pointer
# t7 -- mask for digit
prtany:
li $t7,1
sllv $t7,$t7,$a2 # get mask + 1
subu $t7,$t7,1 # get mask for digit
la $t6,obufe # point one past end of buffer
subu $t6,$t6,1 # point to last char in buffer
sb $zero,0($t6) # store string EOS
move $t5,$s0 # get number
prtany_loop:
and $t0,$t5,$t7 # isolate digit
lb $t0,hexDigit($t0) # get ascii digit
subu $t6,$t6,1 # move output pointer one left
sb $t0,0($t6) # store into output buffer
srlv $t5,$t5,$a2 # slide next number digit into lower bits
sub $a1,$a1,$a2 # bump down remaining bit count
bgtz $a1,prtany_loop # more to do? if yes, loop
# output string
li $v0,4
syscall
# output the number
move $a0,$t6 # point to ascii digit string start
syscall
# output newline
la $a0,nl
syscall
jr $ra # return
我在这里和其他地方在线阅读了很多关于这个主题的话题。关于移位的重要主题(不一定与汇编有关,但一般主题是:What are bitwise shift (bit-shift) operators and how do they work? I've gone as far as copying and pasting the code from the OP here: How do I print a binary number with an inputed integer? 并根据回复者的建议进行更改,无论我做什么,我都会继续生成一串零。
我明白位移是什么以及它是如何工作的。向右移动 'n' 将数字除以 2^n,向左移动将数字乘以 2^n。
上周我有一个实验,它的第三部分是提供一个程序,该程序将接受用户输入,打印出它的二进制版本,然后是十六进制版本。完成后,程序将打印出字符串中心的某些位,并生成其二进制和十六进制版本。
我最初的想法是将字符串与 0x01 相乘,打印结果“1”或“0”,然后将其右移“1”。这包含在一个循环中,并会一直持续到我的计数器满足“32”要求并完成为止。但是我对为什么它打印全是'0'感到非常困惑。我试过其他版本,例如:
将用户输入左移 31,然后对每个位执行循环,但在循环内它向右移动(以弥补位的颠倒顺序)-失败-全部又是零
与上面相反 - 再次失败,全零
我知道我想做什么,就像这样:
(NOT CODE OBVIOUSLY)
User input is: 25 <-- store at $t0
Binary rep is: 0000 0000 0000 0000 0000 0000 0001 1001 # 25 in $t0
LOOP:
AND with 0x01: 0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t1
Produces: 0000 0000 0000 0000 0000 0000 0000 0001 #saved to $t2
Print to Console: 1 #send contents of $t2 to syscall
Shift $t0 Right 1: 0000 0000 0000 0000 0000 0000 0000 1100 #
j LOOP (until the beq branch was met and I left the loop)
我原以为这会奏效。即使它向后产生结果,我想我仍然会在我产生的字符串中收到 '1',我会注意到并相应地处理(将 $t0
中留下的整个数字移动 '31' 然后执行上面的说明。仍然全是“0”...
这是我的代码。现在,由于我的无数次尝试和更改,它又被破坏了。我只是寻求一些帮助,以了解我上面强调的方法是否完全偏离基础,以及我可以对下面的示例代码做些什么来解决这个问题。
了解到此作业已上交,但由于我的困惑而没有完成。我希望进一步了解这一点。我没有完成整个代码,因为我被这部分难住了。所以我只要求这个作业的第一部分。
#Read integer A from user and store it into a register
#Display the integer in binary
#Display the integer in Hex
#set Register $a0 to contain only bits 12,13,14,15 of $a0
#Display the integer in binary contained in $a0
#Display the integer in hex contained in $a0
.data
userInput: .asciiz "Please enter your integer:\n"
binaryInput: .asciiz "Here is the input in binary: "
nl: .asciiz "\n\n"
hexInput: .asciiz "Here is the input in hexidecmal: "
binaryOutput: .asciiz "Here is the output in binary: "
hexOutput: .asciiz "Here is the output in hexidecimal: "
.text
main:
#ask end-user to submit an integer value
li $v0, 4
la $a0, userInput
syscall
#read user-input
li $v0, 5
syscall
#enter user input into $t0
move $t0, $v0
add $t1, $zero, $zero #counter
addi $t2, $zero, 32 #target
sll $s1, $t0, 31 #shift left number 31 bits to s1
li $v0, 4
la $a0, binaryInput #print out string to user
syscall
loop:
andi $s2, $s1, 1 #and 0x01 with s1 to s2
srl $s1, $s1, 1 #shift right s1 by 1 bit
li $v0, 1
la $a0, ($s2) #print digit held in s2 to screen
syscall
add $t1, $t1, 1 #add 1 to counter
bne $t1, $t2, loop #check if counter is equal to target, if not continue loop
#exit the program
li $v0, 10
syscall
这是一种与您的基本方法有些不同的方法。它将二进制输出和十六进制输出视为通用输出函数的参数。位 masking/bit 移位类似,但掩码和位宽可变。
# Read integer A from user and store it into a register
# Display the integer in binary
# Display the integer in Hex
# set Register $a0 to contain only bits 12,13,14,15 of $a0
# Display the integer in binary contained in $a0
# Display the integer in hex contained in $a0
.data
userInput: .asciiz "Please enter your integer: "
binaryInput: .asciiz "Here is the input in binary: "
nl: .asciiz "\n"
hexInput: .asciiz "Here is the input in hexadecimal: "
binaryOutput: .asciiz "Here is the output in binary: "
hexOutput: .asciiz "Here is the output in hexadecimal: "
hexDigit: .asciiz "0123456789ABCDEF"
obuf: .space 100
obufe:
.text
.globl main
main:
# ask end-user to submit an integer value
li $v0,4
la $a0,userInput
syscall
# read user-input
li $v0,5
syscall
move $s0,$v0
# output original in binary
la $a0,binaryInput
li $a1,32
jal prtbin
# output original in hex
la $a0,hexInput
li $a1,32
jal prthex
# isolate bits 12,13,14,15
srl $s0,$s0,12
andi $s0,$s0,0x0F
# output isolated in binary
la $a0,binaryOutput
li $a1,4
jal prtbin
# output isolated in hex
la $a0,hexOutput
li $a1,4
jal prthex
# exit the program
li $v0,10
syscall
# prtbin -- print in binary
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
prtbin:
li $a2,1 # bit width of number base digit
j prtany
# prthex -- print in hex
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
prthex:
li $a2,4 # bit width of number base digit
j prtany
# prtany -- print in given number base
#
# arguments:
# a0 -- output string
# a1 -- number of bits to output
# a2 -- bit width of number base digit
# s0 -- number to print
#
# registers:
# t0 -- current digit value
# t5 -- current remaining number value
# t6 -- output pointer
# t7 -- mask for digit
prtany:
li $t7,1
sllv $t7,$t7,$a2 # get mask + 1
subu $t7,$t7,1 # get mask for digit
la $t6,obufe # point one past end of buffer
subu $t6,$t6,1 # point to last char in buffer
sb $zero,0($t6) # store string EOS
move $t5,$s0 # get number
prtany_loop:
and $t0,$t5,$t7 # isolate digit
lb $t0,hexDigit($t0) # get ascii digit
subu $t6,$t6,1 # move output pointer one left
sb $t0,0($t6) # store into output buffer
srlv $t5,$t5,$a2 # slide next number digit into lower bits
sub $a1,$a1,$a2 # bump down remaining bit count
bgtz $a1,prtany_loop # more to do? if yes, loop
# output string
li $v0,4
syscall
# output the number
move $a0,$t6 # point to ascii digit string start
syscall
# output newline
la $a0,nl
syscall
jr $ra # return