Search code examples
assemblybinaryhexavr

Why do the lsl and lsr functions cause these flags in the SREG


Given the following assembly code:

ldi     r26, 0x00
ldi     r27, 0x01
ldi     r30, 0xAC
lsl     r30
lsr     r30
asr     r30

Immediately following the lsl operation, the H, S, V, and C SREG flags are raised. I do not understand why. I understand that when the lsl operation shifts the bits to the left, that bit 7 raises the C flag. What I don't understand is why the other three flags are raised.

According to the atmel instruction manual, lsl effectively multiplies the value by 2. If r30 starts as 0xAC (172), then why does lsl make it 0x58 (88). This is also the point where all of the flags are raised.

After this operation, I understand why everything else does what it does, as lsr and asr both effectively divide the value by 2. After the lsr operation, r30 is 44, and after the asr operation, r30 is 22.


Solution

  • Since your registers are 8 bits, shifting 0xAC left will lose a bit. 0xAC * 2 = 0x158 but the 1 is lost (is in the carry flag). The remainder is of course the 0x58 you are seeing. The flags are documented in the instruction set reference as:

    H: Rd3

    C: Rd7

    N: Set if MSB of the result is set; cleared otherwise.

    V: N xor C

    S: N xor V

    Rd3 is bit #3 of the input operand. It is set, so H = 1.

    Rd7 is bit #7 of the input operand. It is set, so C = 1.

    MSB of the result is not set, so N = 0.

    V = N xor C = 0 xor 1 = 1

    S = N xor V = 0 xor 1 = 1