【问题标题】:How to do Math(subtraction, multiplication, factorial) and change output to hexadecimal in lc3?如何在lc3中做数学(减法,乘法,阶乘)并将输出更改为十六进制?
【发布时间】:2020-01-15 00:09:07
【问题描述】:

我正在使用 LC3 模拟器,我想将输出从十进制更改为十六进制,正如我在标题中所说,我想知道如何在 LC3 中进行数学运算。我是 LC3 的新手,所以我真的需要帮助。谢谢。

;
; Initialization
;
        .ORIG   x3000
        LD      R6, EMPTY   ; R6 is the stack pointer
        LD      R5, PTR     ; R5 is pointer to characters
        AND     R0, R0, #0
        ADD     R0, R0, #10 ; Print a new line
        OUT
;   
REDO    LDR     R3, R5, #0  ; R3 gets character
;
; Test character for end of file
;       
        ADD     R4, R3, #-10    ; Test for end of line (ASCII xA)
        BRz     EXIT        ; If done, quit
        LD      R4, ZERO
        ADD     R3, R3, R4  ; Get the decimal value from ASCII
        JSR     CONV
        ADD     R5, R5, #1
        AND     R4, R5, #1  ; check odd/even
        BRz     EVEN
        ADD     R2, R3, #0  ; Save the first operand to R2
        LD      R0, PLUS    ; '+'
        OUT
        BRnzp   REDO
EVEN    LD      R0, EQUAL       ; '='
        OUT
; Start calculation
        ADD     R3, R2, R3  ; The second operand is at R3
;
        JSR     CONV
        AND     R0, R0, #0
        ADD     R0, R0, #10 ; Print a new line
        OUT
        BRnzp   REDO        
;
; A subroutine to output a 3-digit decimal result.
;
CONV    ADD     R1, R7, #0  ; R3, R4, R5 and R7 are used in this subroutine
        JSR     Push
        ADD     R1, R3, #0  ; R3 is the input value
        JSR     Push
        ADD     R1, R4, #0
        JSR     Push
        ADD     R1, R5, #0
        JSR     Push
        AND     R5, R5, #0
OUT100  LD      R4, HUNDRED
        ADD     R4, R3, R4  ; R3 - #100
        BRn     PRI100
        LD      R4, HUNDRED
        ADD     R3, R3, R4  ; R3 - #100
        ADD     R5, R5, #1
        BRnzp   OUT100
PRI100  LD      R0, ASCII   ; Load the ASCII template
        ADD     R0, R0, R5      ; Convert binary count to ASCII
        OUT                     ; ASCII code in R0 is displayed.
        AND     R5, R5, #0
OUT10   ADD     R4, R3, #-10
        BRn     PRI10
        ADD     R3, R3, #-10
        ADD     R5, R5, #1
        BRnzp   OUT10
PRI10   LD      R0, ASCII       ; Load the ASCII template
        ADD     R0, R0, R5  ; Convert binary count to ASCII
        OUT                   ; ASCII code in R0 is displayed.      
        LD      R0, ASCII
        ADD     R0, R0, R3      ; Convert binary count to ASCII
        OUT                     ; ASCII code in R0 is displayed.
        JSR     Pop
        ADD     R5, R1, #0
        JSR     Pop
        ADD     R4, R1, #0
        JSR     Pop
        ADD     R3, R1, #0
        JSR     Pop
        ADD     R7, R1, #0
        RET
Push    STR     R1, R6, #0      ; Stack Push
        ADD     R6, R6, #-1 
        RET 
Pop     ADD     R6, R6, #1      ; Stack Pop
        LDR     R1, R6, #0
        RET
; End of the subroutine
EXIT    HALT                    ; Halt machine

PTR     .FILL   x3500
EMPTY   .FILL   x4000 
ASCII   .FILL   x0030           ; '0'
ZERO    .FILL   xFFD0           ; -'0'
HUNDRED .FILL   xFF00           ; -x100
EQUAL   .FILL   x003D           ; '='
PLUS    .FILL   x002B           ; '+'
MINUS   .FILL   x002D           ; '-'
FACTOR  .FILL   x0021           ; '!'
MULT    .FILL   x002A           ; '*'
CHAR_A  .FILL   x0041           ; 'A'
VAL     .BLKW   1
        .END

我从另一个文件中获取输入,它们是这样的,所以在模拟器上它现在会显示为“002+003=005”。我希望它显示 '009+008=011', '009-008=001', '009*008=048', '006!=2D0' 用于加法、减法、乘法和阶乘。

.ORIG       x3500
HELLO   .STRINGZ    "9887766554433221\n" ;this is the other file

【问题讨论】:

    标签: assembly hex lc3


    【解决方案1】:

    如何做减法?

    LC3 没有减法指令。您需要做的是取第二个操作数的负数,并将其添加到第一个操作数。你如何否定第二个操作数? LC3 是一台Two's Complement 机器。所以,你按位不做,然后加 1。

    要在 R0 和 R1 中添加两个数字,并将结果放入 R0,请使用以下程序集:

    ADD R0, R0, R1
    

    要从 R0 中减去 R1(即 R0 - R1)并将结果放入 R0,请使用以下程序集:

    NOT R1, R1
    ADD R1, R1, #1
    ADD R0, R0, R1
    

    这是很多工作,但至少不是乘法!

    如何进行乘法运算?

    ...

    很好。

    有两种方法可以处理乘法。首先是重复添加。想象一下,您将 5 乘以 4。

     5
     5
     5
    +5
    --
    20
    

    所以,你写了一个循环,反复加 5、4 次。如果您尝试将大数相乘,这会变得非常笨拙。

    第二种方法是使用掩码,并在每个循环中将掩码和其中一个操作数向左移动一次。这允许您只在 16 个循环中进行乘法运算。

    如何进行阶乘?

    您创建了一个乘法子例程,并反复使用它来创建一个阶乘子例程。

    我想将输出从十进制改为十六进制

    你很幸运,因为十六进制在 LC3 中比十进制更容易处理。您可以做的是取数字的前 4 位,将它们右移,然后使用查找表来决定要打印的十六进制数字。然后,将原始数字左移 4 位。重复此操作 4 次,您将打印出数字。

    这是一个例子:

    ; assume R0 has the 4-bit number we want to convert to hex
    LEA R1, lookup
    ADD R0, R0, R1 ; go to the cell pointed to by R1, and advance the pointer
                   ; by the number in R1
    LDR R0, R0, #0 ; load the cell pointed to by R0 into R0
    OUT            ; print hex
    lookup .STRINGZ "0123456789ABCDEF"
    

    右移可能很烦人,具体取决于您使用的 LC3 版本。如果使用LC3b,则内置了右移指令。否则,您需要编写一个循环。

    【讨论】:

    • 非常感谢。我也想知道我们如何在 LC3 中进行循环?我以前只用过 Python,所以它们在某种程度上是一样的吗?
    • 这可能是一个足够大的主题,值得单独提出一个问题,但这里是三句话版本:首先,在循环顶部制作一个标签。然后,将寄存器与零进行比较,如下所示:ADD R0, R0, #0(将 R0 替换为要分支的寄存器)最后,使用 BRn、BRz、BRp 或它们的某种组合在循环条件下分支到顶部是真的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多