⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter 4 variables and constants -- valvano.htm

📁 介绍了在嵌入式系统中如何用c来设计嵌入式软件
💻 HTM
📖 第 1 页 / 共 5 页
字号:
unspecified memory (stack) locations, then how does the program find them? This 
is done by using the pointer register (X) to designate a stack frame for the 
currently active function. There is a difference between the ICC11 and ICC12 
compilers. The ICC11 compiler generates code that will define a new value of X 
(executing the <B>tsx</B> instruction) whenever it wishes to access a local 
variable. Consequently we see many <B>tsx</B> instructions throughout the 
function. On the other hand, the ICC12 compiler generates code that attempts to 
define the stack frame pointer x only once at the beginning of the function. 
Consequently we usually see only one <B>tfr s,x</B> instruction in each the 
function. The 6812 <B>tfr s,x</B> instruction is just an alternative 
specification of the instruction <B>tsx</B> (i.e., they produce the same machine 
code and perform the same function when executed). When the ICC12 function is 
entered, the prior value of Register X is pushed onto the stack and then the new 
value of SP is moved to X. The ICC11 function does not save the prior value of 
Register X. This address--the new value of SP--then becomes the base for 
references to local variables that are declared within the function. The 6812 
has a much richer set of machine instructions and addressing modes to simplify 
this process. The 6811 SP register points to a free memory space to be used to 
place the next byte to be pushed. On the other hand the 6812 SP register points 
to the top data byte that has already been pushed.</FONT></P>
<P><FONT face="Times New Roman,Times">In order to understand both the machine 
architecture and the C compiler, we can look at the assembly code generated. For 
both the ICC11 and ICC12 compilers, the linker/loader allocates 3 segmented 
memory areas: code pointed to by the PC (<I>text area</I>); global accessed with 
absolute addressing (<I>data area</I>); and locals pointed to by the stack 
pointer SP. This example shows a simple C program with three local variables. 
Although the function doesn't do much it will serve to illustrate how local 
variables are created (allocation), accessed (read and write) and destroyed 
(deallocated.)</FONT></P>
<DIR>
<P><CODE>void sub(void){ short y1,y2,y3;&nbsp;&nbsp;&nbsp;/* 3 local 
variables*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;y1=1000;<BR>&nbsp;&nbsp;&nbsp;&nbsp;y2=2000;<BR>&nbsp;&nbsp;&nbsp;&nbsp;y3=y1+y2;<BR>}</CODE></P></DIR>
<ADDRESS><FONT face="Times New Roman,Times">Listing 4-9: Example showing three 
local variables</FONT></ADDRESS>
<P><FONT face="Times New Roman,Times">The first compiler we will study is the 
ImageCraft ICC11 version 4.0 for the Motorola 6811. The disassembled output has 
been edited to clarify its operation (although the compiler does create the 
";&nbsp;y3&nbsp;-&gt;&nbsp;0,x" comment). The <B>pshx</B> instruction allocates 
the local variable, and the <B>tsx</B> instruction establishes a stack frame 
pointer, X. </FONT></P>
<DIR>
<P><CODE>&nbsp;&nbsp;&nbsp;&nbsp;.area&nbsp;text&nbsp;&nbsp;&nbsp;; _sub in 
ROM<BR>&nbsp;&nbsp;&nbsp;&nbsp;.globl&nbsp;_main<BR>;&nbsp;y3&nbsp;-&gt;&nbsp;0,x<BR>;&nbsp;y2&nbsp;-&gt;&nbsp;2,x<BR>;&nbsp;y1&nbsp;-&gt;&nbsp;4,x<BR>_sub:&nbsp;pshx&nbsp;&nbsp;; 
allocate y1<BR>&nbsp;&nbsp;&nbsp;&nbsp;pshx&nbsp;&nbsp;&nbsp;&nbsp;; allocate 
y2<BR>&nbsp;&nbsp;&nbsp;&nbsp;pshx&nbsp;&nbsp;&nbsp;&nbsp;; allocate 
y3<BR>&nbsp;&nbsp;&nbsp;&nbsp;tsx<BR>&nbsp;&nbsp;&nbsp;&nbsp;ldd&nbsp;&nbsp;#1000&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;std&nbsp;&nbsp;4,x&nbsp;&nbsp;&nbsp;;&nbsp;y1=1000<BR>&nbsp;&nbsp;&nbsp;&nbsp;ldd&nbsp;&nbsp;#2000<BR>&nbsp;&nbsp;&nbsp;&nbsp;std&nbsp;&nbsp;2,x&nbsp;&nbsp;&nbsp;;&nbsp;y2=2000<BR>&nbsp;&nbsp;&nbsp;&nbsp;ldd&nbsp;&nbsp;4,x<BR>&nbsp;&nbsp;&nbsp;&nbsp;addd&nbsp;2,x<BR>&nbsp;&nbsp;&nbsp;&nbsp;std&nbsp;&nbsp;0,x&nbsp;&nbsp;;&nbsp;y3=y1+y2<BR>&nbsp;&nbsp;&nbsp;&nbsp;pulx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 
deallocate 
y3<BR>&nbsp;&nbsp;&nbsp;&nbsp;pulx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 
deallocate 
y2<BR>&nbsp;&nbsp;&nbsp;&nbsp;pulx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 
deallocate y1<BR>&nbsp;&nbsp;&nbsp;&nbsp;rts</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">The stack frame at the time of the 
<B>addd</B> instruction is shown. Within the subroutine the local variables of 
other functions are not accessible.</FONT></P>
<CENTER>
<P><IMG height=103 
src="Chapter 4 Variables and Constants -- Valvano.files/stack11a.gif" 
width=218></P></CENTER>
<ADDRESS>Figure 4-1. 6811 stack frame showing three local variables.</ADDRESS>
<P><FONT face="Times New Roman,Times">The next compiler we will study is the 
ImageCraft ICC12 version 5.0 for the Motorola 6812. Again, the disassembled 
output has been edited to clarify its operation (although the compiler does 
create the "</FONT><FONT face=Courier>;&nbsp;y3&nbsp;-&gt;&nbsp;-6,x</FONT><FONT 
face="Times New Roman,Times">" comment). Like the 6811, the linker/loader also 
allocates 3 segmented memory areas: code pointed to by the PC; global accessed 
with absolute addressing; and locals pointed to by the stack pointer SP. 
The</FONT><FONT face=Courier> <B>leas -6,sp</B></FONT><FONT 
face="Times New Roman,Times"> instruction allocates the local variables, and 
the</FONT><B><FONT face=Courier> tfr s,x</FONT></B><FONT face=Courier> 
</FONT><FONT face="Times New Roman,Times">instruction establishes a stack frame 
pointer, X. Within the subroutine the local variables of other functions are not 
accessible.</FONT></P>
<CENTER>
<P><IMG height=322 
src="Chapter 4 Variables and Constants -- Valvano.files/lv.gif" 
width=370>&nbsp;</P></CENTER>
<ADDRESS>Figure 4-2. 6812 implementation of three local variables.</ADDRESS>
<P>&nbsp;</P>
<P><FONT face="Times New Roman,Times"><A name=CONSTANTLOCAL></A>A <B>constant 
local</B> is similar to the regular local. Just as with the other locals, the 
constant is defined temporarily on the stack. The difference is that the 
constant local can not be changed. The assembly language code generated by the 
compiler that accesses the constant local is identical to the regular local. 
</FONT></P>
<DIR>
<P><CODE>short TheGlobal;&nbsp;&nbsp;&nbsp;/* a regular global 
variable*/<BR>void main(void){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;const short 
TheConstant=1000;&nbsp;&nbsp;&nbsp;/* a constant 
local*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;TheGlobal=TheConstant;<BR>}</CODE></P></DIR>
<ADDRESS>Listing 4-10: Example showing a constant local </ADDRESS>
<P><FONT face="Times New Roman,Times">The 6811 code generated by the ICC11 
(Version 4) compiler is as follows</FONT></P>
<DIR>
<P><CODE>&nbsp;&nbsp;&nbsp;&nbsp;.area&nbsp;text&nbsp;&nbsp;&nbsp;; _main in 
ROM<BR>&nbsp;&nbsp;&nbsp;&nbsp;.global 
_main<BR>;&nbsp;TheConstant&nbsp;-&gt;&nbsp;0,x<BR>_main: pshx&nbsp;&nbsp;; 
allocate 
TheConstant<BR>&nbsp;&nbsp;&nbsp;&nbsp;tsx<BR>&nbsp;&nbsp;&nbsp;&nbsp;ldd&nbsp;&nbsp;#1000<BR>&nbsp;&nbsp;&nbsp;&nbsp;std&nbsp;&nbsp;0,x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;TheConstant=1000<BR>&nbsp;&nbsp;&nbsp;&nbsp;std&nbsp;&nbsp;_TheGlobal&nbsp;&nbsp;;&nbsp;TheGlobal=TheConstant<BR>&nbsp;&nbsp;&nbsp;&nbsp;pulx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; 
deallocate 
TheConstant<BR>&nbsp;&nbsp;&nbsp;&nbsp;rts<BR>&nbsp;&nbsp;&nbsp;&nbsp;.area 
bss<BR>&nbsp;&nbsp;&nbsp;&nbsp;.global _TheGlobal<BR>_TheGlobal: .blkb 2 
</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">The 6812 code generated by the ICC12 
(Version 5.1) compiler is as follows</FONT></P>
<DIR>
<P><CODE>&nbsp;&nbsp;&nbsp;&nbsp;.area text <BR>_main:: 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;pshx<BR>&nbsp;&nbsp;&nbsp;&nbsp;tfr 
s,x<BR>&nbsp;&nbsp;&nbsp;&nbsp;leas -2,sp <BR>&nbsp;&nbsp;&nbsp;&nbsp;movw 
#1000,-2,x <BR>&nbsp;&nbsp;&nbsp;&nbsp;movw -2,x,_TheGlobal 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;tfr 
x,s<BR>&nbsp;&nbsp;&nbsp;&nbsp;pulx<BR>&nbsp;&nbsp;&nbsp;&nbsp;rts 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;.area bss <BR>_TheGlobal:: .blkb 2 </CODE></P>
<P>&nbsp;</P></DIR>
<P><B><I><FONT face=Helvetica,Arial><A 
name=EXTERNAL></A>Externals</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Objects that are defined outside of the 
present source module have the external storage class. This means that, although 
the compiler knows what they are (signed/unsigned, 8-bit 16-bit 32-bit etc.), it 
has no idea where they are. It simply refers to them by name without reserving 
space for them. Then when the linker brings together the object modules, it 
resolves these "pending" references by finding the external objects and 
inserting their addresses into the instructions that refer to them. The compiler 
knows an external variable by the keyword <B>extern</B> that must precede its 
declaration.</FONT></P>
<P><FONT face="Times New Roman,Times">Only global declarations can be designated 
extern and only globals in other modules can be referenced as 
external.</FONT></P>
<P><FONT face="Times New Roman,Times">The following example sets an external 
global, called <B>ExtGlobal</B>, to the value 1000. This global can be 
referenced by any function from any file in the software system. It is truly 
global.</FONT></P>
<DIR>
<P><CODE>extern short ExtGlobal;&nbsp;&nbsp;&nbsp;/* an external global 
variable*/<BR>void main(void){ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;ExtGlobal=1000;&nbsp;&nbsp;&nbsp;&nbsp;<BR>}</CODE></P></DIR>
<ADDRESS>Listing 4-11: Example showing an external global</ADDRESS>
<P><FONT face="Times New Roman,Times">Notice the assembly language the ICC11 
generates does not include the definition of <B>ExtGlobal</B>. The 6811 code 
generated by the ICC11 (Version 4) compiler is as follows</FONT></P>
<DIR>
<P><CODE>&nbsp;&nbsp;&nbsp;&nbsp;.area text <BR>&nbsp;&nbsp;&nbsp;&nbsp;.global 
_main<BR>_main:<BR>&nbsp;&nbsp;&nbsp;&nbsp;ldd #1000 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;std _ExtGlobal <BR>&nbsp;&nbsp;&nbsp;&nbsp;rts 
</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">Similarly the assembly language the ICC12 
generates also does not include the definition of <B>ExtGlobal</B>. The 6812 
code generated by the ICC12 (Version 5.1) compiler is as follows</FONT></P>
<DIR>
<P><CODE>&nbsp;&nbsp;&nbsp;&nbsp;.area text <BR>_main:: 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;movw #1000,_ExtGlobal 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;rts </CODE></P>
<P>&nbsp;</P></DIR>
<P><B><I><FONT face=Helvetica,Arial><A name=SCOPE></A>Scope</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">The <I>scope</I> of a variable is the 
portion of the program from which it can be referenced. We might say that a 
variable's scope is the part of the program that "knows" or "sees" the variable. 
As we shall see, different rules determine the scopes of global and local 
objects.</FONT></P>
<P><FONT face="Times New Roman,Times">When a variable is declared globally 
(outside of a function) its scope is the part of the source file that follows 
the declaration--any function following the declaration can refer to it. 
Functions that precede the declaration cannot refer to it. Most C compilers 
would issue an error message in that case. </FONT></P>
<P><FONT face="Times New Roman,Times">The scope of local variables is the block 
in which they are declared. Local declarations must be grouped together before 
the first executable statement in the block--at the head of the block. This is 
different from C++ that allows local variables to be declared anywhere in the 
function. It follows that the scope of a local variable effectively includes all 
of the block in which it is declared. Since blocks can be nested, it also 
follows that local variables are seen in all blocks that are contained in the 
one that declares the variables.</FONT></P>
<P><FONT face="Times New Roman,Times">If we declare a local variable with the 
same name as a global object or another local in a superior block, the new 
variable temporarily supersedes the higher level declarations. Consider the 
following program.</FONT></P>
<DIR>
<P><CODE>unsigned char x;&nbsp;&nbsp;&nbsp;/* a regular global 
variable*/<BR>void 
sub(void){<BR>&nbsp;&nbsp;&nbsp;&nbsp;x=1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; 
unsigned char x;&nbsp;&nbsp;&nbsp;/* a local 
variable*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x=2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;unsigned 
char x;&nbsp;&nbsp;/* a local 
variable*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x=3;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTA=x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTA=x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;PORTA=x;}<BR>}</CODE></P></DIR>
<ADDRESS>Listing 4-12: An example showing the scope of local variables</ADDRESS>
<P><FONT face="Times New Roman,Times">This program declares variables with the 
name <B>x</B>, assigns values to them, and outputs them to PORTA with in such a 
way that, when we consider its output, the scope of its declarations becomes 
clear. When this program runs, it outputs 321. This only makes sense if the 
<B>x</B>declared in the inner most block masks the higher level declarations so 
that it receives the value '3' without destroying the higher level variables. 
Likewise the second <B>x</B>is assigned '2' which it retains throughout the 
execution of the inner most block. Finally, the global <B>x</B>, which is 
assigned '1', is not affected by the execution of the two inner blocks. Notice, 
too, that the placement of the last two <B>PORTA=x;</B> statements demonstrates 
that leaving a block effectively unmasks objects that were hidden by 
declarations in the block. The second<B> PORTA=x; </B>sees the middle 
<B>x</B>and the last <B>PORTA=x;</B> sees the global <B>x</B>.</FONT></P>
<P><FONT face="Times New Roman,Times">This masking of higher level declarations 
is an advantage, since it allows the programmer to declare local variables for 
temporary use without regard for other uses of the same names.</FONT></P>
<P><FONT face="Times New Roman,Times">One of the mistakes a C++ programmer makes 
when writing C code is trying to define local variables in the middle of a 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -