在汇编程序中移动(移位)两个寄存器

Posted

技术标签:

【中文标题】在汇编程序中移动(移位)两个寄存器【英文标题】:Moving (shifting) two registers in Assembler 【发布时间】:2012-01-04 23:34:19 【问题描述】:

我有 8 个 LED 和 2 个按钮,最初第一个和最后一个 LED 点亮,如果我按下第一个按钮,第一个 LED 向右移动,如果我按下第二个按钮,最后一个 LED 向左移动。如果两盏灯“相遇”,通过相互转换,它们就会关闭。

我不知道如何在按下按钮后更新单行的 LED,所以我为每个按钮制作了 2 行,P1 和 P2。第一行似乎正确移动,但第二行真的搞砸了。我做错了什么?

下面是我的代码:

$TITLE(5)
$MOD51
ORG 100H
START: 
    ; 8 leds, P1.0-P1.7
    ; 2 buttons, P0.1 P0.2
    MOV P1, #00h
    MOV P2, #00h

    ; left LED positions
    MOV 30H, #00000001b ; initial position
    MOV 31H, #00000010b  
    MOV 32H, #00000100b  
    MOV 33H, #00001000b  
    MOV 34H, #00010000b             
    MOV 35H, #00100000b  
    MOV 36H, #01000000b  
    MOV 37H, #10000000b 

    MOV 38H, #00000000b ; leds meet

    ; right led positions
    MOV 39H, #10000000b ; initial position
    MOV 40H, #01000000b  
    MOV 41H, #00100000b  
    MOV 42H, #00010000b  
    MOV 43H, #00001000b             
    MOV 44H, #00000100b  
    MOV 45H, #00000010b  
    MOV 46H, #00000001b  

    MOV R1, #0
    MOV R2, #0

 LOOP:  
    JNB P0.1, INCREMENT_L ; left button pressed, led shifts right
    JNB P0.2, INCREMENT_R ; right button pressed, led shifts left

    CALL DISP_L ; display left led
    CALL DISP_R ; display right led

    JMP LOOP

INCREMENT_L:
    SETB P0.1
    CJNE R1, #7, INC_L
    MOV R1, #0
    JMP LOOP

INCREMENT_R:
    SETB P0.2
    CJNE R2, #7, INC_R
    MOV R2, #0
    JMP LOOP

INC_L:
    MOV A, R2
    ADD A, #39H
    MOV B, A
    MOV A, R1
    ADD A, #30H
    CJNE A, B, INCL
    JMP RESET
    JMP LOOP

INC_R:
    MOV A, R1
    ADD A, #30H
    MOV B, A
    MOV A, R2
    ADD A, #39H
    CJNE A, B, INCR
    JMP RESET
    JMP LOOP

INCL:
    INC R1
    JMP LOOP

INCR:
    INC R2
    JMP LOOP

DISP_L:
    MOV A, R1
    ADD A, #30H
    MOV R0, A
    MOV P1, @R0
    RET

DISP_R: 
    MOV A, R2
    ADD A, #39H
    MOV R0, A
    MOV P2, @R0
    RET

RESET:
    MOV R1, #0
    MOV R2, #0
    JMP LOOP

END

【问题讨论】:

定义为“搞砸了”。它在做什么?另外,您是否尝试过注释掉几行代码以查看它的反应? 如果您期望得到有用的答案,您需要提供更多上下文。最起码是什么 CPU 和 LED/按钮是如何连接的。 “搞砸了”,如在使用 sim535 程序进行测试时,第一行 LED 会“干净地”移动,从 10000000(其中 0 表示未点亮的 LED,1 表示点亮的 LED)到 00000001 (一次移动 1 个 LED),而第二行在第一次按下按钮时显示 11111100 而不是 00000010,在第二次按下时显示 01111010 而不是 00000100,然后是其他奇怪的值 【参考方案1】:

这听起来很像签名/未签名的问题。您的添加是无符号的,还是假设高位是符号位并为您做 2s 恭维的东西。如果不小心,任何剩余的进位也可能会影响事情。你有直接移位指令而不是使用加法吗?

快速上网,发现您确实有一个 SHL/SHR 指令,您可以使用它来移动您的位。然后,如果它们匹配,您只需对您的位置进行异或即可关闭该位。

【讨论】:

哦,所以我只有 2 个寄存器,一个包含 00000001,另一个包含 10000000 作为初始值,并使用 SHR / SHL 移动位。还有一个问题:我如何“合并”这两个寄存器中的位?例如,如果我有 00001000 和 1000000 并且我想将它们“合并”到 10001000 我使用的是 8x51 架构,所以我有 RRC 和 RLC 而不是 SHR / SHL 使用异或。如果位相同,它将返回 0。类似于 dhl r0,与 r1 进行异或并放在 r2 中。显示 r2。其他方式相同,shr r1,与 r0 异或,放置并显示在 r2 中。那应该会给您想要的结果。顺便说一句,使用 RRC 和 RLC(假设它意味着通过进位向左旋转和通过进位向右旋转)意味着您可以将设置位在任一方向上一直通过灯光移动,进入进位,然后通过重复调用旋转。有点整洁。

以上是关于在汇编程序中移动(移位)两个寄存器的主要内容,如果未能解决你的问题,请参考以下文章

stm32串口——标志位学习

在编制乘除法程序时,为啥常用移位指令来代替乘除法指令?

CCD移位寄存器 的工作原理是啥啊

ARM NEON:如何对整个 64 位 d 寄存器进行位移?

Atmega32 移位 PORTA 不会循环遍历整个寄存器

按寄存器中的值移位位