Hallo, I was working to find the cause of "far variable in expression producing wrong result". Now I modified the previous test program and checked the assembler code generated. Here is my C program:
#include <Philips\reg51m.h> unsigned int result ; unsigned int v1 = 25 ; far unsigned int v2 = 25 ; unsigned char N = 2 ; void main () { result = (v1 * N) + (v1 / 10) ; // expected 52 result = (v2 * N) + (v2 / 10) ; // expected 52 }
; result = (v1 * N) + (v1 / 10) ; // expected 52 ; SOURCE LINE # 10 MOV R7,N MOV R6,#00H ; R6-R7 = N (converted to unsigned int) MOV R4,v1 MOV R5,v1+01H; R4-R5 = v1 LCALL ?C?IMUL ; calculate (v1 * N) ; probably, answer stored in R6-R7 (?) MOV R2,AR6 MOV R3,AR7 ; copy the answer to R2-R3 MOV R6,v1 MOV R7,v1+01H; R6-R7 = v1 MOV R4,#00H MOV R5,#0AH ; R4-R5 = 10 (converted to unsigned int) LCALL ?C?UIDIV; calculate (v1 / 10) ; probably, answer stored in R6-R7 (?) ; R6-R7 = (v1 / 10) and also ; R2-R3 = (v1 * N) ; hence add them to get the result MOV A,R3 ADD A,R7 MOV result+01H,A MOV A,R2 ADDC A,R6 MOV result,A
; result = (v2 * N) + (v2 / 10) ; // expected 52 ; SOURCE LINE # 11 MOV R7,N MOV R6,#00H ; R6-R7 = N (converted to unsigned int) MOV R3,#BYTE2 (v2) MOV R2,#HIGH (v2) MOV R1,#LOW (v2) ; PR0 is pointing to v2 EMOV A,@PR0 ; read high byte of v2 MOV R4,A ; copy it into R4 EMOV A,@PR0+01H ; read low byte of v2 MOV R5,A ; copy it into R5 ; hence R4-R5 = v2 LCALL ?C?IMUL ; calculate (v2 * N) ; probably, answer stored in R6-R7 (?) ; in the previous case, this intermediate answer was ; copied to R2-R3 ; but here it is not so! ; maybe, because R2-R3 are needed for something else? MOV R3,#BYTE2 (v2) ; why to reload r3? MOV R2,#HIGH (v2) ; why to reload r2? EMOV A,@PR0 MOV R6,A EMOV A,@PR0+01H MOV R7,A ; now R6-R7 = v2 MOV R4,#00H MOV R5,#0AH ; R4-R5 = 10 LCALL ?C?UIDIV ; calculate (v1 / 10) ; probably, answer stored in R6-R7 (?) ; R6-R7 = (v1 / 10) ; but R2-R3 is NOT (v1 * N) !!! ; I think this is causing the problem MOV A,R3 ADD A,R7 MOV result+01H,A MOV A,R2 ADDC A,R6 MOV result,A