📄 chapter 10 functions -- valvano.htm
字号:
y<BR> pulx ;deallocate
z1<BR> rts<BR> .globl
_main<BR>; y ->
4,x<BR>_main:<BR> pshx ;allocate
y<BR> pshx ;allocate temporary
(z3)<BR> pshx ;allocate temporary
(z2)<BR> tsx<BR> ldd #1000<BR> std _x1 ;x1=1000<BR> std _x2 ;x2=1000<BR> ldd _x3<BR> std 2,x ;z3=x3<BR> ldd _x2<BR> std 0,x ;z2=x2<BR> ldd _x1 ;RegD=x1<BR> jsr _add3<BR> tsx<BR> std 4,x ;y=x1+x2+x3<BR> pulx ;deallocate
temporary
(z2)<BR> pulx ;deallocate
temporary
(z3)<BR> pulx ;deallocate
y<BR> rts<BR> .area
bss ;RAM<BR>_x2: .blkb 2<BR> .globl
_x1<BR>_x1: .blkb 2</CODE></P></DIR>
<ADDRESS>Listing 10-10: ICC11 assembly of function call with local
variables</ADDRESS>
<P><FONT face="Times New Roman,Times">The stack frame at the time of the
</FONT><B><FONT face=Courier>addd</FONT></B><FONT face="Times New Roman,Times">
instructions is shown in Figure 10-3. Within the subroutine the local variables
of main are not accessible.</FONT></P>
<P><IMG height=218 src="Chapter 10 Functions -- Valvano.files/Image39.gif"
width=330></P>
<ADDRESS>Figure 10-3: ICC11 stack within the add3 function</ADDRESS>
<P> </P>
<P><FONT face="Times New Roman,Times">The second compiler we will study is the
ImageCraft ICC12 version 5.1 for the Motorola 6812. This disassembled output
also has been edited to clarify its operation. The linker/loader 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 global symbols,
<B>_x1 _x2_x3</B>, will be assigned or bound by the linker/loader. The three
instructions <B>pshx tfr s,x </B>and<B> leas -8,sp</B> allocates the local
variable, and establishes a stack frame pointer, X. This compiler passes the
first input parameter (<B>z1</B>) into the subroutine by placing it in register
D. The remaining parameters (<B>z2</B>, <B>z3</B> in this example) are pushed on
the stack by the main program before the subroutine is called. The first
operation the subroutine performs is to push the remaining parameter on the
stack (<B>pshd</B>) so that all three parameters,<B> z1 z2 z3</B>, are on the
stack. Also notice that the <B>main</B> program allocates space for the
parameters it needs to push when it calls <B>add3</B> at the beginning of
<B>main</B>.</FONT></P>
<P> </P>
<ADDRESS><IMG height=224 src="Chapter 10 Functions -- Valvano.files/Image40.gif"
width=333></ADDRESS>
<ADDRESS>Figure 10-4: ICC12 stack within the add3 function</ADDRESS>
<DIR>
<P><CODE> .area text<BR>_x3:: .word
1000<BR> .area text<BR>; y -> -2,x<BR>; z3 ->
8,x<BR>; z2 -> 6,x<BR>; z1 -> 2,x<BR>_add3::
pshd<BR> pshx<BR> tfr
s,x<BR> leas -2,sp<BR> ldd
2,x<BR> addd 6,x<BR> addd
8,x<BR> std -2,x<BR> ldd
-2,x<BR> tfr
x,s<BR> pulx<BR> leas
2,sp<BR> rts<BR>; y -> -2,x<BR>_main::
pshx<BR> tfr s,x<BR> leas
-8,sp<BR> movw #1000,_x1<BR> movw
#1000,_x2<BR> movw
_x3,2,sp<BR> movw _x2,0,sp<BR> ldd
_x1<BR> jsr _add3<BR> std
-4,x<BR> tfr d,y<BR> sty
-2,x<BR> tfr
x,s<BR> pulx<BR> rts<BR>.area
bss<BR>_x2: .blkb 2<BR>_x1:: .blkb
2</CODE></P></DIR>
<ADDRESS>Listing 10-11: ICC12 assembly of function call with local
variables</ADDRESS>
<P><A name=ANIMATION></A><IMG height=395
src="Chapter 10 Functions -- Valvano.files/stck.gif" width=393></P>
<ADDRESS>Figure 10-5: ICC12 animation of the add3 function</ADDRESS>
<P><B><I><FONT face=Helvetica,Arial><A name=FSM></A>Finite State Machine using
Function Pointers</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Now that we have learned how to declare,
initialize and access function pointers, we can create very flexible finite
state machines. In the finite state machine presented in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap9/chap9.htm#FSMDEFINITION">Listing
9-2</A> and <A
href="http://www.ece.utexas.edu/~valvano/embed/chap9/chap9.htm#FSMPROGRAM">Listing
9-4</A>, the output was a simple number that is written to the output port. In
this next example, we will actually implement the exact same machine, but in a
way that supports much more flexibility in the operations that each state
performs. In fact we will define a general C function to be executed at each
state. In this implementation the functions perform the same output as the
previous machine.</FONT></P>
<P><IMG height=205 src="Chapter 10 Functions -- Valvano.files/fsm.GIF"
width=387></P>
<ADDRESS>Figure 10-6: Finite State Machine (same as Figure 9-1)</ADDRESS>
<P><FONT face="Times New Roman,Times">Compare the following implementation to <A
href="http://www.ece.utexas.edu/~valvano/embed/chap9/chap9.htm#FSMDEFINITION">Listing
9-2</A>, and see that the <B>unsigned char Out;</B> constant is replaced with a
<B>void (*CmdPt)(void);</B> function pointer. The three general function
<B>DoStop() DoTurn()</B> and <B>DoBend()</B> are also added.</FONT></P>
<DIR>
<P><CODE>const struct State{<BR> </CODE><FONT
face=Courier size=2>void</FONT><CODE> </CODE><FONT face=Courier
size=2>(*CmdPt)(void);</FONT><CODE> </CODE><FONT face=Courier
size=2>/* function to execute
*/</FONT><CODE><BR> unsigned int Wait; /* Time (E cycles) to wait */<BR> unsigned char AndMask[4];<BR> unsigned char EquMask[4];<BR> const struct State *Next[4];}; /* Next states */<BR>typedef const struct State StateType;<BR>typedef StateType * StatePtr;<BR>#define stop &fsm[0]<BR>#define turn &fsm[1]<BR>#define bend &fsm[2]<BR></CODE><FONT
face=Courier size=2>void DoStop(void){</FONT><CODE> </CODE><FONT
face=Courier size=2>PORTH=0x34;}</FONT><CODE><BR></CODE><FONT face=Courier
size=2>void DoTurn(void){</FONT><CODE> </CODE><FONT face=Courier
size=2>PORTH=0xB3;}</FONT><CODE><BR></CODE><FONT face=Courier size=2>void
DoBend(void){</FONT><CODE> </CODE><FONT face=Courier
size=2>PORTH=0x75;}</FONT><CODE><BR>StateType fsm[3]={<BR>{</CODE><FONT
face=Courier
size=2>&DoStop</FONT><CODE>, 2000, // stop 1 ms<BR> {0xFF, 0xF0, 0x27, 0x00},<BR> {0x51, 0xA0, 0x07, 0x00},<BR> {turn, stop, turn, bend}},<BR>{</CODE><FONT
face=Courier
size=2>&DoTurn</FONT><CODE>,5000, // turn 2.5 ms<BR> {0x80, 0xF0, 0x00, 0x00},<BR> {0x00, 0x90, 0x00, 0x00},<BR> {bend, stop, turn, turn}},<BR>{</CODE><FONT
face=Courier
size=2>&DoBend</FONT><CODE>,4000, // bend 2 ms<BR> {0xFF, 0x0F, 0x01, 0x00},<BR> {0x12, 0x05, 0x00, 0x00},<BR> {stop, stop, turn, stop}}};</CODE></P></DIR>
<ADDRESS>Listing 10-12: Linked finite state machine structure stored in
ROM</ADDRESS>
<P> </P>
<P><FONT face="Times New Roman,Times"><A name=CONTROL></A>Compare the following
implementation to <A
href="http://www.ece.utexas.edu/~valvano/embed/chap9/chap9.htm#FSMPROGRAM">Listing
9-4</A>, and see that the <B>PORTH=pt-Out;</B> assignment is replaced with a
<B>(*Pt->CmdPt)();</B> function call. In this way, the appropriate function
<B>DoStop() DoTurn()</B> or <B>DoBend()</B> will be called.</FONT></P>
<DIR>
<P><CODE>void control(void){ StatePtr Pt;<BR> unsigned char Input; int Endt; unsigned int i;<BR> </CODE><FONT
face=Courier size=2>TSCR |=0x80;</FONT><CODE> </CODE><FONT
face=Courier size=2>// TEN(enable)</FONT><CODE><BR> </CODE><FONT
face=Courier size=2>TMSK2=0xA2;</FONT><CODE> </CODE><FONT
face=Courier size=2>// TOI arm, TPU(pullup) timer/4
(500ns)</FONT><CODE><BR> DDRH=0xFF; // PortH bits 7-0 are outputs<BR> DDRJ=0x00; // PortJ bits 7-0 are inputs<BR> PUPSJ=0xFF; // Pullups J7-J0<BR> PULEJ=0xFF; // Enable pull up/down PortJ<BR> Pt=stop; // Initial State <BR> while(1){<BR> </CODE><FONT
face=Courier
size=2>(*Pt->CmdPt)();</FONT><CODE> </CODE><FONT
face=Courier size=2>//</FONT><CODE> </CODE><FONT face=Courier
size=2>1)</FONT><CODE> </CODE><FONT face=Courier
size=2>execute</FONT><CODE> </CODE><FONT face=Courier
size=2>function</FONT><CODE><BR> Endt=TCNT+Pt->Wait; // Time (500
ns
each) to wait<BR> while(Endt-TCNT>0); // 2) wait <BR> Input=PORTJ; // 3) input <BR> for(i=0;i<4;i++)<BR> if((Input&Pt->AndMask[i])==Pt->EquMask[i]){<BR> Pt=Pt->Next[i]; // 4) next depends on input<BR> i=4; }}};</CODE></P></DIR>
<ADDRESS>Listing 10-13: Finite state machine controller for
MC68HC812A4</ADDRESS>
<P><B><I><FONT face=Helvetica,Arial><A name=INTERPRETER></A>Linked List
Interpreter using Function Pointers</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">In the next example, function pointers are
stored in a listed-list. An interpreter accepts ASCII input from a keyboard and
scans the list for a match. In this implementation, each node in the linked list
has a function to be executed when the operator types the corresponding letter.
The linked list <B>LL</B> has three nodes. Each node has a letter, a function
and a link to the next node. </FONT></P>
<P><CODE>// Linked List Interpreter<BR>const struct
Node{<BR> unsigned char Letter;
<BR> void
(*fnctPt)(void);<BR> const struct Node *Next;};
<BR>typedef const struct Node NodeType;<BR>typedef NodeType * NodePtr;<BR>void
CommandA(void){<BR> OutString("\nExecuting Command a");
<BR>}<BR>void CommandB(void){<BR> OutString("\nExecuting
Command b"); <BR>}<BR>void
CommandC(void){<BR> OutString("\nExecuting Command c");
<BR>}<BR>NodeType LL[3]={<BR> { 'a', &CommandA,
&LL[1]},<BR> { 'b', &CommandB,
&LL[2]},<BR> { 'c', &CommandC, 0 }};<BR>void
main(void){ NodePtr Pt; char string[40];<BR> InitSCI();
// Enable SCI port<BR> TSCR |=0x80; //
TEN(enable)<BR> TMSK2=0xA2; // TOI
arm, TPU(pullup) timer/4 (500ns)<BR> OutString("\nEnter a
single letter command followed by <enter>");
<BR> while(1){<BR> OutString("\n>");
<BR> InString(string,39); //
first character is
interpreted<BR> Pt=&LL[0]; //
first node to
check<BR> while(Pt){<BR> if(string[0]==Pt->Letter){<BR> Pt->fnctPt(); //
execute
function<BR> break;} //
leave while
loop<BR> else{<BR> Pt=Pt->Next;<BR> if(Pt==0)
OutString(" Error");}}}}<BR></CODE></P>
<ADDRESS>Listing 10-14: Linked list implementation of an interpreter.</ADDRESS>
<P><FONT face="Times New Roman,Times">Compare the syntax of the function call,
<B>(*Pt->CmdPt)();</B>, in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap10/CONTROL">Listing
10-13</A>, with the syntax in this example, <B>Pt->fnctPt();</B>. In the
Imagecraft compilers, these two expressions both generate code that executes the
function. </FONT></P>
<P><FONT face="Times New Roman,Times">Go to <A
href="http://www.ece.utexas.edu/~valvano/embed/chap11/chap11.htm">Chapter 11 on
Preprocessor Directives</A> Return to <A
href="http://www.ece.utexas.edu/~valvano/embed/toc1.htm">Table of
Contents</A></FONT></P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -