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.
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