0
votes

i have the following assembly code for atmega1280 on a bigavr board.

;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

the code should perform the logical operation: LED0: (PA1 ^ PA2) v PA3

But i don't understand how it works. My assumption: With in temp, PIN i can read out the values on the input pins. If PORTA1 and PORTA3 is activated, PIN should return 00000101 . okay, in prepare_operands this is moved into variables pa1,pa2 and pa3. for for pa1 it is shifted one times to the right. So pa1 contains 00000010. on pa1 there a addi operation is performed, why? how does this work?

2

2 Answers

1
votes

The code is trying to place a 0x1 in the operand if the mask has a bit in a certain position.

First, each of pa1, pa2, and pa3 is shifted a different amount to get the bit of interest into the far right end. Then the "and with immediate 0x1" clears all the bits in the variable except for the rightmost, and leaves the rightmost unchanged.

The variable will contain either 0x0 or 0x1, depending on the value of the bit of interest.

0
votes

I don't see any addi instruction in the code you've posted. If you mean andi then the purpose is to mask off any additional bits that might have been set besides the one that is of interest.

temp is set to PIN & 0xf, so it could have any value in the range 0x0..0xf. If temp happened to be 0xf and you just set pa1 to temp >> 1 then you'd get 0x7. But since the intention of prepare_operands appears to be to place the n:th bit in pan it does a bitwise AND after the shift (e.g. 0xf >>1 == 0x7, 0x7 & 1 == 1).