MIPS 程序集将整数转换为二进制并读取 1 的个数?

MIPS Assembly converting integer to binary and reading the number of 1's?

我正在开发一个程序,它从用户那里获取一个整数,然后输出它的二进制等价物中有多少个 1。所以首先我认为我需要将它转换为二进制,然后使用循环检查所有 32 位以找出有多少个 1。

我已经浏览了几个小时,并尝试了不同的方法来首先将整数转换为二进制。最好的方法是什么?有没有办法直接读取二进制的寄存器值,还是需要先转换?这是我目前所有的代码。

  .data
EnterInteger: .asciiz "Enter an integer: "


.text
 # Print the first message
 li $v0, 4
 la $a0, EnterInteger
 syscall

 # Prompt the user to enter the first integer
 li $v0, 5
 syscall

 # Store the first integer in $t0
 move $t0, $v0

这是我目前拥有的代码,但无法正常工作。当我输入 4673 时,我应该得到“4”,而我只得到“1”

    .data
Msg: .asciiz "Enter an integer: "



.text
 # Print the first message
 li $v0, 4
 la $a0, Msg
 syscall

 # Prompt the user to enter the first integer
 li $v0, 5
 syscall

 # Store the first integer in $t0
 move $t0, $v0

 addi $t3, $zero, 0

main:
 bgt $t3, 32, exit
 andi $t0, $v0, 1
 bne $t0, $zero, count 
 



count:
 addi $t3, $t3, 1
 addi, $t1, $zero, 1
 # Shift to the next bit and then go back to main
 srl $t0, $t0, 1
 j main
 
exit:

# Tell the interpreter to get read to print an integer
 li $v0, 1
 add $a0, $zero, $t1
 
 #Print the integer
 syscall
 
 # End the program
 li $v0, 10
 syscall

正如 Michael 评论的那样,寄存器中的整数已经是二进制的。寄存器是一组 32 位。

至关重要的是,对寄存器 的操作,如andi $t1, $v0, 1srl $v0, $v0, 1 以二进制 工作。即 and 的结果 0 或 1 是值 mod 2,并且 right-shift 除以 1 位除以 2.

这是因为 MIPS 是一个 二进制 计算机,就像每个超过 real-world 的 ISA 一样,你可能会为之学习汇编。 Higher-level 语言,包括具有 &>> 操作的 C、Java 和 Python 也始终保证它们以二进制形式工作。 (在 non-binary 计算机上,例如三进制,为 x & y 实现这些语义将涉及转换为 base-2 数字数组并手动执行逻辑,然后再转换回来。)

如果您想使用其他基数,例如基数 10,您需要进行实际除法 (MIPS divu) 或余数以移除或隔离最低的基数 10 数字。或者,如果基数是 2 的幂,例如基数 16,则移动 4 位,或与 0x0f 进行与运算(取低 4 位,即 0b1111)。


其他基数的输入/输出涉及将(二进制)整数从 / 转换为代表另一个基数的 ASCII 数字串。 MARS/SPIM read_int 调用(syscall with $v0 = 5)为你完成了,就像 C 库函数 scanf 或 printf。要手动执行此操作,您需要执行类似 total = total * 10 + digit 的操作,其中 digit 类似于 ascii_char - '0'。或者对于输出,重复将 / modulo 除以 10 以获得以 10 为基数的数字,从最低位开始。

有一些关于手动转换 to/from 字符串的 MIPS 问答,但并不多,因为大多数使用 MIPS 的学生都在使用 MARS 或 SPIM 以及他们的玩具系统调用,这些系统调用通常由 C 库或由手。但如果你搜索的话,IIRC 也有一些。

ASCII 十进制或十六进制字符串是数字的序列化格式,而不是它们在计算机中的存在方式(字符串除外,不是整数)。


人口数

一次循环一个位,提取并添加低位,是一种计算设置位数的简单但通常效率低下的方法。尽管如此,简单对于第一次尝试还是有好处的;选择 andisrl 作为前面的示例是一个提示。

How to count the number of set bits in a 32-bit integer? 上显示了一些更快的 bithack,尽管对于 MIPS 这意味着生成大量单独的 32 位常量,每个常量需要 2 条指令。您可以执行两个 SWAR 加宽步骤,然后遍历 4 位总和组,作为中间地带。

shows a way where you count iterations of n &= n-1 to clear the lowest set bit,如果只设置了几个位,速度会更快,即使它们不在寄存器底部附近。