简体   繁体   English

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

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

I am working on a program that takes an integer from the user and then outputs how many 1's there are in it's binary equivalent.我正在开发一个程序,它从用户那里获取一个 integer,然后输出它的二进制等价物中有多少个 1。 So first I believe I need to convert it to binary and then use a loop and check all 32 bits to find how many 1's there are.所以首先我认为我需要将它转换为二进制,然后使用循环检查所有 32 位以找出有多少个 1。

I have been browsing around for hours and trying different things to first convert the integer to binary.我已经浏览了几个小时,并尝试了不同的方法来首先将 integer 转换为二进制文件。 What's the best way to do this?最好的方法是什么? Is there a way to to read a register value in binary directly, or do I need to convert it first?有没有办法直接读取二进制的寄存器值,还是需要先转换? This is all the code I have so far.这是我到目前为止的所有代码。

  .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

Here is the code I have so far but it's not working.这是我到目前为止的代码,但它不起作用。 When I input 4673 I should get "4", instead I only get "1"当我输入 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

As Michael commented, integers in registers are already in binary .正如迈克尔评论的那样,寄存器中的整数已经是二进制的 A register is a group of 32 bits.寄存器是一组 32 位。

Crucially, operations on registers like andi $t1, $v0, 1 and srl $v0, $v0, 1 work in binary .至关重要的是,像andi $t1, $v0, 1srl $v0, $v0, 1这样的寄存器操作以二进制形式工作 ie the resulting 0 or 1 from and is the value mod 2, and right-shift by 1 place divides by 2.and的结果 0 或 1 是值 mod 2,右移 1 位除以 2。

This is a consequence of MIPS being a binary computer, like every over real-world ISA you might learn assembly for.这是 MIPS 是二进制计算机的结果,就像您可能为之学习汇编的所有现实世界 ISA 一样。 Higher-level languages including C, Java, and Python that have & and >> operations also always guarantee that they work in binary.具有&>>操作的高级语言,包括 C、Java 和 Python 也始终保证它们以二进制形式工作。 (On a non-binary computer, eg ternary, implementing those semantics for x & y would involve converting to an array of base-2 digits and doing the logic manually, then converting back.) (在非二进制计算机上,例如三元计算机,实现x & y的这些语义将涉及转换为 base-2 数字数组并手动执行逻辑,然后再转换回来。)

If you want to work with other number bases, like base 10, you'd need to do actual division (MIPS divu ) or remainder to remove or isolate the lowest base-10 digit.如果您想使用其他基数,例如基数 10,则需要进行实际除法 (MIPS divu ) 或余数以移除或隔离最低的基数 10 数字。 Or if the base is a power of 2, like base 16, then shift by 4 bits, or AND with 0x0f (take the low 4 bits, ie 0b1111).或者,如果基数是 2 的幂,如基数 16,则移动 4 位,或与0x0f进行与运算(取低 4 位,即 0b1111)。


Input / output in other bases involves converting (binary) integers from / to strings of ASCII digits representing digits in another base.在其他基数中输入 / output 涉及将(二进制)整数从 / 转换为表示另一个基数中数字的 ASCII 数字字符串。 The MARS/SPIM read_int call ( syscall with $v0 = 5) does that for you, like C library functions scanf or printf. To do it manually, you do stuff like total = total * 10 + digit , where digit is something like ascii_char - '0' . MARS/SPIM read_int 调用(带 $v0 = 5 的syscall )会为您执行此操作,例如 C 库函数 scanf 或 printf。要手动执行此操作,您需要执行诸如total = total * 10 + digit之类的操作,其中digit类似于ascii_char - '0' Or for output, repeated division / modulo by 10 to get the base-10 digits, starting with the lowest.或者对于 output,重复除以/取模 10 以获得以 10 为基数的数字,从最低位开始。

There are some MIPS Q&As about manually converting to/from strings, but not many because most students using MIPS are using MARS or SPIM with their toy system calls that do things normally done by a C library, or by hand.有一些关于手动转换为字符串/从字符串转换的 MIPS 问答,但并不多,因为大多数使用 MIPS 的学生都使用 MARS 或 SPIM 和他们的玩具系统调用,这些系统调用通常由 C 库或手动完成。 But IIRC there are some if you search.但是如果你搜索的话,IIRC 有一些。

ASCII decimal or hex strings are a serialization format for numbers, not how they exist inside computers (except as strings, not integers). ASCII 十进制或十六进制字符串是数字的序列化格式,而不是它们在计算机中的存在方式(字符串除外,不是整数)。


Popcount人口统计

Looping over the bits one at a time, extracting and adding the low bit, is a simple but often inefficient way to count the number of set bits.一次循环一个位,提取并添加低位,是一种计算设置位数量的简单但通常效率低下的方法。 Still, simple is good for a first attempt;尽管如此,简单对于第一次尝试还是有好处的; the choice of andi and srl as examples earlier is a hint.前面示例中选择的andisrl是一个提示。

Some faster bithacks are shown on How to count the number of set bits in a 32-bit integer? How to count the number of set bits in a 32-bit integer? 上显示了一些更快的 bithacks? although for MIPS that means generating lots of separate 32-bit constants which cost 2 instructions each.尽管对于 MIPS,这意味着生成许多单独的 32 位常量,每个常量需要 2 条指令。 You could do two SWAR widening steps and then loop over groups of 4-bit sums, as a middle ground.您可以执行两个 SWAR 加宽步骤,然后循环遍历 4 位和的组,作为中间地带。

Count bits 1 on an integer as fast as GCC __builtin__popcount(int) shows a way where you count iterations of n &= n-1 to clear the lowest set bit , which is faster if there are only a few bits set, even if they're not near the bottom of the register. 将 integer 上的位 1 计数为 GCC __builtin__popcount(int)显示了一种计算n &= n-1的迭代次数以清除最低设置位的方法,如果只设置了几个位,则速度更快,即使它们'不在收银机底部附近。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM