This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

far variable in expression (MX)

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
}

The first statement works ok.
But the second statement produces wrong
result (2 instead of 52). The only difference
in these 2 statements is that:
one uses v1 (variable in data memory)
second uses v2 (far variable)
Both v1 and v2 are set to same value (25)
and that value can be correctly seen in
simulator.

I compared the assembler code generated for
these 2 statements.
Here is the assembler code generated for
first statement (which works ok)
(it includes many comments from me!)
I can guess that subroutines with funny
names (such as ?C?IMUL) are actually
library subroutines which do the math
(multiply or divide etc). My conclusion
is based on this guess.

; 	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

Now compare this with the assembler lines
generated for second statement (which
produces wrong result):

; 	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

Again, I think it is a bug.

Keil: is there a solution to this? If not,
then soon I will be in very bad situation :(
My program is big and I use many many far
variables and I often use them in many more
complicated expressions. I have so many
variables that I must use far. I can not
use xdata. Also the start address of my
external memory is not 0, hence xdata is
not possible. What can I do?

Please also look at my earlier messages on
similar subject:
http://www.keil.com/forum/docs/thread3583.asp
http://www.keil.com/forum/docs/thread3576.asp
<

0