我在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
操作,为什么?这是怎么回事?
答案 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)。