2013-03-09 138 views
0

我在bigavr板上有atmega1280的以下汇编代码。AVR汇编逻辑运算

;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   ;(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

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

回答

0

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

temp设置为PIN & 0xf,所以它可以在0x0..0xf范围内有任何值。如果temp碰巧是0xf,而您只是将pa1设置为temp >> 1,那么您会得到0x7。但是因为prepare_operands的意图似乎是将第n位放置在pan中,所以它在移位之后(例如,0xf >> 1 == 0x7,0x7 & 1 == 1)进行按位AND。

1

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

首先,pa1,pa2和pa3中的每一个被移位一个不同的数量,以便将最感兴趣的位移到最右端。然后“和立即0x1”清除变量中除最右侧以外的所有位,并保持最右侧不变。

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