0

我在 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操作,为什么?这是如何运作的?

4

2 回答 2

1

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

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

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

于 2013-03-09T20:51:45.613 回答
0

addi我在您发布的代码中没有看到任何说明。如果您的意思是andi,那么目的是屏蔽除感兴趣的位之外可能已设置的任何其他位。

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

于 2013-03-09T19:07:16.697 回答