【问题标题】:Assembly language strange error汇编语言奇怪的错误
【发布时间】:2013-03-04 22:55:46
【问题描述】:

我是汇编语言的新手,遇到了一个奇怪的错误。该程序应该显示用户输入的整数的 4 个最低有效位。它适用于大于 8 的数字,但对于小于或等于 8 的数字,它会输出应该在的数字。对于 8,它输出 8000 而不是 1000,对于 5,它输出 0401。我不明白为什么,谁能帮忙?

        .data
inPrompt:   .asciiz "Enter an integer: "
outLab:     .asciiz "Least significant 4 bits of int entered are "
############################ code segment ################################
        .text
        .globl main
main:
        li $v0, 4
        la $a0, inPrompt        
        syscall                   # print input prompt

        li $v0, 5
        syscall                   # read input integer

        move $t0, $v0

        li $v0, 4
        la $a0, outLab        
        syscall

        li $v0, 1

        andi $a0, $t0, 8               
                syscall

        andi $a0, $t0, 4             
                syscall

        andi $a0, $t0, 2             
                syscall

        andi $a0, $t0, 1        
                syscall
          ##########################################################

                li $v0, 10               # exit
                syscall

【问题讨论】:

    标签: assembly mips


    【解决方案1】:

    问题在于您正在有效地计算和打印 数字的加法分解(以 2 的幂的因数)而不是其位。

    简单地说,例如对于“第 4 位”
    andi $a0, $t0, 4
    将导致存储在寄存器A0...
    - .. 值 4 如果寄存器 T0 中的值的附加因子为 4(例如 4、5、6、7、12、13 等)

    - ... 如果 T0 中的值不具有 4 的附加因子(例如 0、1、2、3、8、9、10 等),则值为 0。

    这解释了为什么 5 会得到 0401,因为 5 is 4 + 1 或更准确地说是 5 is 0 * 8 + 4 + 0 * 2 + 1

    你需要做的是其中之一两件事:

    • 测试andi操作结果是否为非零,在这种情况下,在调用syscall之前将1加载到$a0
    • [按位] 将andi 运算的结果移动相应的位数(测试“8 位”时移动3 次,测试“4 位”时移动2 次,测试“2 位”时移动一次)

    第一个建议将导致类似以下内容,以代替“andi + syscall”组:

                andi $a0, $t0, 4
                blez $a0, outBit4  # bit is zero output integer value 0
                li $a0, 1          # bit is one  ouptut integer value 1 (repl 4 by 1)
      outBit4:  syscall
    

    编辑
    将程序保持在 16 LoC 以下...(顺便说一句,此要求和其他提示表明 homework 所以我将提供一般的想法,而不是给出代码)
    有几种方法可以缩短代码,但考虑到设置使用了 9 行代码,16 LoC 的要求有点困难:提示用户输入、获取输入并保存它,然后输出答案的开头...

    最常见的方法是使用一个(或多个嵌套的)循环。在这种情况下,一个循环就足够了,基本上您需要重复 4 次几乎相同的事情,因此以添加一些 LoC 来管理循环本身(即增加参数和检测循环结束条件)为代价,您可以编写一个 sn-p 以参数化方式处理单个工作单元,并在循环中包含此逻辑。

    一个稍微相关的方法是使用子程序,将重复的逻辑写在一个子程序中,然后可以多次调用,传递不同的参数来实现参数化的行为。

    我提到上面的内容是因为它们在汇编语言中非常常用,并且确实用于大型编程。然而,以目前的“基于andi”的逻辑,恐怕这两种方法都不会将事情带入16 LoC 以下。您可能需要使用循环结构位移逻辑。

    【讨论】:

    • 我曾尝试实施您的第一个建议,但我只能使用 16 行代码,我无法管理它。因为如果它为零,我需要输出那两个,所以我需要两个分支,对吗?对于您的第二个建议,您是指 sll 还是 sra?
    • @EmilyAnnHall a) 如果它是 0,它也会根据建议的 sn-p 输出;不需要else:在这两种情况下,我们都输出,唯一的区别是如果为零,我们将设置值跳过为1。b)第二个建议意味着SRL,即右移逻辑(尽管因为我们只有正值, SRA 将具有相同的效果)c)关于将内容保持在 16 行以下,请参阅编辑。
    • 你的第二个建议完全奏效了!你太棒了,我非常感谢你的帮助。
    猜你喜欢
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多