AVR inline assembler: incorrect evaluation of 16 bit constants
Original Reporter info from Mantis: georghieber
-
Reporter name: Georg Hieber
Original Reporter info from Mantis: georghieber
- Reporter name: Georg Hieber
Description:
apparently, the assembler only evaluates the lower 8 bit of a 16 bit constant.
Given the following declarations:
const
cFE = $FE;
c102 = $102;
c1000 = $1000;
c3070 = $3070;
var
var1: byte;
varabs: byte absolute $100;
the following code:
asm
sts cFE, r22 //(1)
sts c102, r22 //(2)
sts c1000, r22 //(3)
sts c3070, r22 //(4)
sts var1, r22 //(5)
adiw r28, c3070 //(6)
adiw 0x1225 //(7)
// (8) sts varabs, r22
// (9) sts 0x1223, r22
end;
translates to (lines 1 to 7)
# [33] sts cFE, r22 sts -2,r22 # [34] sts c102, r22 sts 2,r22 # [35] sts c1000, r22 sts 0,r22 # [36] sts c3070, r22 sts 112,r22 # [37] sts var1, r22 sts (U_sPsCONCEPTS_ss_VAR1),r22 # [38] adiw r28, c3070 adiw r28,112 # [39] adiw 0x1225 adiw 37
line (8), if uncommented, results in the error message: "Error: Unsupported symbol type for operand", line (9) in "Fatal: Syntax error, "(" expected but "," found".
comments:
(1)
I don't know, what the assembler makes out of -2. Probably not 0x00FE, but in 16 bit arithmetics 0xFFFE, wich is certainly not the address where I wanted to store r22.
(2), (3), (4)
the upper 8 bits are simply ignored.
(5)
is correct
(6)
the compiler again ignores the upper 8 bits. The compilation produces an assembler file, but ends with the error message: "Error: Error while assembling exitcode 1". The assembler correcly states "argument out of range" for "adiw r28, 112"
(7)
While the argument here certainly is way out of range, nobody complains...
(8)
This is probably not part of the bug reported here, but due to the fact that the compiler does not create an assembler symbol for absolute variables, but inserts their address directly into the generated code. The question is, however, if he can do this when compiling Pascal code, why not as well when compiling assembler code?
(9)
This is, IMHO, a completely correct assembler statement. So, what is happening?
Additional information:
The previously reported issue hi8 / lo8 seems to be a direct symptom of this one.
I consider this issue critical. It makes it simply impossible to access an absolute memory address in assembler code, except by tricky constructs like loading the adress bytewise into an index register and accessing indirectly. Especially, it prohibits access to the upper I/O - registers.