I have a memory mapped A/D converter (with a conversion time << one machine cycle, therefore no need to check for End of Conversion). The following code was written to explain the problem: -
xdata unsigned char A_D _at_ 0xE000; //this is the address of the A/D converter unsigned char x,y; main() { A_D = 0; //start conversion by doing a "dummy write" x = A_D; // read the value from the A/D }
CLR A MOV DPTR,#A_D(E000) MOVX @DPTR,A MOV x(0x80),A
"However, the question remains - why should I need to do anything at all?" If you look up 'volatile' in a decent 'C' book you'll realise that the optimisation you're seeing is exactly what 'C' compilers are expected to do. In embedded stuff you'll find yourself using volatile quite a bit to suppress this when dealing with memory mapped peripherals and interrupt service routines.