AVR汇编逻辑运算

时间:2013-03-09 17:52:03

标签: assembly avr

我在bigavr主板上有atmega1280的以下汇编代码。

;Set PA3:0 to input without pull-up and PA7:4 to output and use PORTA7:4 for LED0-3.

.nolist
.include "m1280def.inc"
.list

.equ PORT, PORTA
.equ DDR, DDRA
.equ PIN, PINA

.equ temp, 0x10
.equ pa1, 0x11
.equ pa2, 0x12
.equ pa3, 0x13

.section .text
.globl main
.org 0x0000

    rjmp    main

main:
main_init_stack_ptr:
    ldi     temp, lo8(RAMEND)
    out     SPL, temp
    ldi     temp, hi8(RAMEND)
    out     SPH, temp

main_init_ports:
    ldi     temp, 0x0
    out     PORT, temp
    ldi     temp, 0xf0          ; 7654 3210 (PORTA index)
    out     DDR, temp           ; oooo iiii (i/o state)

main_loop:
    in      temp, PIN
    andi    temp, 0x0f

    rcall   set_led0

    out     PORT, temp

    rjmp    main_loop

set_led0:                       ; PORT << 4: (1 & 2) | 3
    rcall   prepare_operands

    and     pa1, pa2
    or      pa3, pa1

    sbrs    pa3, 0
    ret
    sbr     temp, 0b00010000
    ret


prepare_operands:               ; move inputs 1..3 to pa1..3
    mov     pa1, temp           ; and shift/mask them the LSB
    mov     pa2, temp
    mov     pa3, temp
    lsr     pa1
    lsr     pa2
    lsr     pa2
    lsr     pa3
    lsr     pa3
    lsr     pa3
    andi    pa1, 0x01
    andi    pa2, 0x01
    andi    pa3, 0x01
    ret

代码应执行逻辑操作:LED0: (PA1 ^ PA2) v PA3

但我不明白它是如何运作的。 我的假设: 使用in temp, PIN,我可以读出输入引脚上的值。如果激活PORTA1和PORTA3,则PIN应返回00000101。好吧,在prepare_operands中,这被移入变量pa1,pa2和pa3。对于pa1,它向右移动一次。所以pa1包含00000010。在pa1上执行addi操作,为什么?这是怎么回事?

2 个答案:

答案 0 :(得分:1)

如果掩码在某个位置有一个位,代码会尝试在操作数中放置一个0x1。

首先,将pa1,pa2和pa3中的每一个移位不同的量,以使感兴趣的位进入最右端。然后“和即时0x1”清除变量中除最右边之外的所有位,并保持最右边不变。

变量将包含0x0或0x1,具体取决于感兴趣的位的值。

答案 1 :(得分:0)

我在您发布的代码中没有看到任何addi指令。如果你的意思是andi,那么目的是掩盖除了感兴趣的那些之外可能已经设置的任何其他位。

temp设置为PIN & 0xf,因此它可以包含0x0..0xf范围内的任何值。如果temp碰巧是0xf,而您只是将pa1设置为temp >> 1,那么您将获得0x7。但是由于prepare_operands的意图似乎是将{n}位置于pa n中,它在移位后执行按位AND(例如,0xf&gt;&gt; 1 == 0x7,0x7&amp; 1 == 1)。