We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello all, I'm using Keil uVision2 Version 7.05, and everything seems to be OK. However, there is one thing I don't quite understand, thus I'm posting here asking for your ideas/opinions. When I run "Hello" example in Keil\Example directory and I found something that puzzled me. The assembly code Keil generated in Disamsembly window as well as in list file always have MOVX command eventhough I don't use external ram at all. I did set memory model to small and I only use IDATA but it still does the same. I even use disamsembler to translate the hex file Keil generated back to assembly source and still get the same result. Can someone spend some times explain this for me? Any inputs would be greatly appreciated. Have a nice weekend. Best Regards, T.L
Can you specify an address where you see the MOVX instruction? Following is the entire assembler code from the listing file for HELLO.C. It contains no MOVX instructions that I can see.
; FUNCTION main (BEGIN) ; SOURCE LINE # 23 ; SOURCE LINE # 29 0000 759850 MOV SCON,#050H ; SOURCE LINE # 30 0003 438920 ORL TMOD,#020H ; SOURCE LINE # 31 0006 758DDD MOV TH1,#0DDH ; SOURCE LINE # 32 0009 D28E SETB TR1 ; SOURCE LINE # 33 000B D299 SETB TI 000D ?C0001: ; SOURCE LINE # 41 ; SOURCE LINE # 42 000D 639001 XRL P1,#01H ; SOURCE LINE # 43 0010 7BFF MOV R3,#0FFH 0012 7A00 R MOV R2,#HIGH ?SC_0 0014 7900 R MOV R1,#LOW ?SC_0 0016 120000 E LCALL _printf ; SOURCE LINE # 44 0019 80F2 SJMP ?C0001 ; FUNCTION main (END)
Dear Jon, Thank you for your prompt reply. Yes, I see it now. Sorry for inaccurated information from my previous post about code in list file. But can you tell me what are these lines doing in that code? Here is partial copy of Disamsembly screen when I run in Simulation Mode, not the whole file:
C?CLDPTR: C:0x0370 BB0106 CJNE R3,#0x01,C:0379 C:0x0373 8982 MOV DPL(0x82),R1 C:0x0375 8A83 MOV DPH(0x83),R2 C:0x0377 E0 MOVX A,@DPTR C:0x0378 22 RET C:0x0379 5002 JNC C:037D C:0x037B E7 MOV A,@R1 C:0x037C 22 RET C:0x037D BBFE02 CJNE R3,#OCRDL(0xFE),C:0382 C:0x0380 E3 MOVX A,@R1 C:0x0381 22 RET C:0x0382 8982 MOV DPL(0x82),R1 C:0x0384 8A83 MOV DPH(0x83),R2 C:0x0386 E4 CLR A C:0x0387 93 MOVC A,@A+DPTR C:0x0388 22 RET C?CLDOPTR: C:0x0389 BB010C CJNE R3,#0x01,C:0398 C:0x038C E582 MOV A,DPL(0x82) C:0x038E 29 ADD A,R1 C:0x038F F582 MOV DPL(0x82),A C:0x0391 E583 MOV A,DPH(0x83) C:0x0393 3A ADDC A,R2 C:0x0394 F583 MOV DPH(0x83),A C:0x0396 E0 MOVX A,@DPTR C:0x0397 22 RET C:0x0398 5006 JNC C:03A0 C:0x039A E9 MOV A,R1 C:0x039B 2582 ADD A,DPL(0x82) C:0x039D F8 MOV R0,A C:0x039E E6 MOV A,@R0 C:0x039F 22 RET C:0x03A0 BBFE06 CJNE R3,#OCRDL(0xFE),C:03A9 C:0x03A3 E9 MOV A,R1 C:0x03A4 2582 ADD A,DPL(0x82) C:0x03A6 F8 MOV R0,A C:0x03A7 E2 MOVX A,@R0 C:0x03A8 22 RET C:0x03A9 E582 MOV A,DPL(0x82) C:0x03AB 29 ADD A,R1 C:0x03AC F582 MOV DPL(0x82),A C:0x03AE E583 MOV A,DPH(0x83) C:0x03B0 3A ADDC A,R2 C:0x03B1 F583 MOV DPH(0x83),A C:0x03B3 E4 CLR A C:0x03B4 93 MOVC A,@A+DPTR C:0x03B5 22 RET
X03b6: cjne r3,#1,X03bf mov dpl,r1 mov dph,r2 movx @dptr,a ret ; X03c3: cjne r3,#0feh,X03c7 movx @r1,a X03c7: ret ; X037d: cjne r3,#0feh,X0382 movx a,@r1 X0381: ret ; X0389: cjne r3,#1,X0398 mov a,dpl add a,r1 mov dpl,a mov a,dph addc a,r2 mov dph,a movx a,@dptr ret ; X03a0: cjne r3,#0feh,X03a9 mov a,r1 add a,dpl mov r0,a movx a,@r0 ret
The first section of code looks like library code. The libraries can handle all sorts of pointers. Those CJNEs and JNCs you see are looking at the tag byte to figure out what kind of pointer it is. If you're not using xdata, then those branches of the code wouldn't actually be executed. I don't remember a xdata-free memory model with libraries that can't reference xdata at all. (Smaller than small? "Tiny"?) But then, I haven't looked in the manual.
Yep. That's pretty much it. The printf function takes generic pointers and, therefore, must have code that can access all memory areas. Disassembling a program like this and trying to examine it is pointless. It's like writing a book review based on the words from one paragraph in the middle of the novel. Jon
Thank you Jon and Drew for your explainations. I'm very comfortable programming 8051 with Assembly, but I'm totally new to C, please bare with me. One more thing here Jon as you said that
The printf function takes generic pointers and, therefore, must have code that can access all memory areas
Are there anyways to tell compiler not generate code that access all the memory areas if it's not needed? What you failed to understand so far is that the movx'es you found are not actually generated by the compiler. They're found in generic routines pulled in from the run-time library, by the linker. Nor does this code necessarily access unused memory classes --- it just has the potential to do so, in case that you did have stuff stored there. I.e. your code will only ever reach any of those movx instructions by exercising undefined behaviour. If you insist on doing so, the way to tell the tools not to link in these functions is to not call any library functions that operate on generic pointers (in the case at hand, printf()).
"Are there anyways to tell compiler not generate code that access all the memory areas if it's not needed?" The code to implement printf() was not generated when you compiled your code. printf is a module in a library what was generated by Keil as part of its toolchain distribution. For your code, use the small model and when using pointers in your routines, use explicit memory space qualifiers. "Because I see the assembly code is only few lines as it shows in the list file, but the hex code takes roughly more than 1kbyte at the compiling time ... Or there is something that I'm missing here?" More accurately, that would be "takes roughly more than 1kbyte at the linking time". Look at the linker map file and find out where all that code is coming from -- printf(), no doubt. Since this example does not need formatted output, printf() is overkill. Try using puts() instead and check the size.
Dear Hans and Dan, Thank you very much for your kind explanations. I'll try as your suggestions. It might take me a while to understand the whole process of linking, compiling, and calling library ...etc and so on. As Erik used to say: "It's bible time". I think I have to read more Keil C manual and try do digest it as much as I can. Besides, I'm also reading "C51 Primer", and "The Final Word on the 8051". Hopefully, after reading all this I'll get a better grasp of C programming for 8051. Once again thanks for your attentions. Have a great day. Best Regards, T.L
Wow!!!! I tried the puts instead of printf as Dan said, and the code went from 1186 bytes down to 251 bytes. It's amazing. One more question here forks: Is there any penalty for doing this? Because I see the "Hello World" print out on the screen seem to be a little bit slower than using printf. Is it just my feeling or it's something else that I don't know of? Thank you all. Best Regards, T.L
"I tried the puts instead of printf as Dan said, and the code went from 1186 bytes down to 251 bytes. It's amazing." It shouldn't be in the least amazing at all! Look at the description of printf in the Manual - it runs to five pages! It should thus be obvious that printf is an extrmely powerful and complex function - it should come as no surprise that it takes a lot of code to implement all that stuff!! See: http://www.keil.com/forum/docs/thread2741.asp
i like to met some one becouse i don't have no wife and no child so if the is one for me then let her cool me eney time i well be ther i am chritian and am 30 old and i am loking for eney one to start my new life with her
"What's he doing here?" Well, isn't it just the obvious place to look for a girlfriend...?
"Well, isn't it just the obvious place to look for a girlfriend...?" You aren't trying to tell me I've been wasting my time here all these years, are you?