【问题标题】:Printing a binary number in LC-3 Assembly在 LC-3 组件中打印二进制数
【发布时间】:2017-04-09 01:45:41
【问题描述】:

我正在尝试使用 LC-3 组件将二进制数打印到控制台。

到目前为止我尝试过的包括(但不限于):

        binary .fill b10000110
        lea r0, binary
        puts ; prints garbage
        ld r0, binary
        out ; prints 0 (I know it only prints one character but I don't know why it chooses to print 0)
        lea r1, binary
        and r2, r2, #0
loop    ldr r0, r1, r2
        out
        add r2, r2, #1
        and r3, r3, #0
        not r3, r2
        add r3, r3, #1
        add r3, r3, #8 ; I know all the binary numbers will be exactly 8 bits long
        brz end
        add r3, r3, #0 ; to be safe
        brnzp loop
end
        ; more code...

这些都不是特别有效。我正在努力找出正确的方法来做到这一点,但我所想的一切都依赖于 binary 是一个字符串,这是我做不到的。

【问题讨论】:

    标签: assembly lc3


    【解决方案1】:

    在 LC-3 中,OUTtrap 子例程获取当前存储在寄存器R0 中的值,找到相应的 ASCII 值并将其输出到控制台,而PUTtrap 子例程获取存储在 @ 中的值987654324@ 作为内存,并遍历存储在该地址的所有数据,将每个字节作为 ASCII 输出到控制台,直到找到一个 NULL 字符。

    在您给出的示例中,PUTS 将打印出 b10000110 的 ASCII 表示,然后是垃圾,直到它碰巧遇到 NULL 字符,而 OUT 将简单地打印 b10000110 的 ASCII 表示。

    随后,要实际打印 0 或 1,我们必须打印这些数字的 ASCII 表示,而不是数字本身。所以,我们定义了两个词,一个用于 ASCII 字符0,另一个用于1

    ascii0  .fill x30
    ascii1  .fill x31
    

    因此,对于任何 1 位数字,我们可以通过简单的 if-else 分支和 OUT 子例程将其打印到控制台。

    binary  .fill b1
            LD  R1, binary
            AND R0, R1, #1
            BRnz else
            LD  R0, ascii1
            BRnzp done
    else    LD  R0, ascii0
    done    OUT
    

    现在,我们必须将其扩展到 n 位。也就是说,我们必须将我们的 n 位数字分解成一系列我们可以轻松打印的 1 位数字。为此,我们只需要一个简单的AND 和第 ith 位的掩码(例如,给定 8 位数字 b10000110,以确定第 3rd sup> 最低有效位,我们将使用掩码 b00000100)。因此,对于 8 位数字,我们将需要掩码序列b10000000b01000000、...、b00000001。有几种方法可以做到这一点,例如从b10000000 开始,每个位左移/乘以 2,但是为了简单起见,我们将使用查找表。

    masks   .fill b10000000
            .fill b01000000
            .fill b00100000
            .fill b00010000
            .fill b00001000
            .fill b00000100
            .fill b00000010
            .fill b00000001
    

    要在打印出每个位之前选择掩码,我们可以使用一个简单的 for 循环分支。

            AND R4, R4, #0   ;clears the register we will count with
            LD  R1, binary
            LEA R2, masks    ;finds the address in memory of the first mask
    loop    LDR R3, R2, #0   ;load the mask from the address stored in R2
            ADD R2, R2, #1   ;next mask address
            AND R0, R1, R3
            ;print out 1-bit number
            ADD R4, R4, #1
            ADD R0, R4, #-8  ;sets condition bit zero when R4 = 8
            BRn loop         ;loops if R4 < 8
    

    最后,我们完成了程序。

            .ORIG x3000
    
            AND R4, R4, #0   ;clears the register we will count with
            LD  R1, binary
            LEA R2, masks    ;finds the address in memory of the first mask
    loop    LDR R3, R2, #0   ;load the mask from the address stored in R2
            ADD R2, R2, #1   ;next mask address
            AND R0, R1, R3
            BRnz else 
            LD  R0, ascii1
            BRnzp done
    else    LD  R0, ascii0
    done    OUT
            ADD R4, R4, #1
            ADD R0, R4, #-8  ;sets condition bit zero when R4 = 8
            BRn loop         ;loops if R4 < 8
            HALT
    
    masks   .fill b10000000
            .fill b01000000
            .fill b00100000
            .fill b00010000
            .fill b00001000
            .fill b00000100
            .fill b00000010
            .fill b00000001
    ascii0  .fill x30
    ascii1  .fill x31
    binary  .fill b10000110
            .END
    

    【讨论】:

    • 干杯 - 我最终使用了一种非常相似的方法:)
    • 如果您将'0' 移动到寄存器中并有条件地添加1,它会简化分支。 (我想从内存中加载'0' 是有道理的,但如果已知 PC 位于低 256B 的地址空间中,您可以使用 LEA 在位置相关代码中加载一个小常量。)
    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2013-04-16
    • 2018-10-23
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多