Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Introduction to Microcontrollers. Architecture, Programming, and Interfacing of the Motorola 68HC12 (G.J. Lipovski, 1999).pdf
Скачиваний:
190
Добавлен:
12.08.2013
Размер:
29.57 Mб
Скачать

274 Chapter 9 Implementationof C Procedures

9.4 Loop Statements, Arrays, and Structs

In this section, we show how statements within a loop can be repeated until a condition is met, governed by an expression much like the expressions of the conditional statements. First, we consider an accumulation of variables incremented or decremented in the loop, in different loop constructs. Then we discuss array elements accessed using indexes. Struct elements are accessed using AND, OR, and shift operations. We will access a two-dimensional array using indexes in for loops and a struct in a do while loop.

The for and while statements test the condition before the loop is executed and are useful if, for example, a loop may have to be done 0 times. The do while statement performs the statement once before it tests the condition. See Figure 9.10.

int i;

main(){ int j, k;

 

 

 

 

 

for(j = k = 0;

j != i;

j++) k +=

j;

 

while(j != 0)

k += —j;

 

 

 

do k += j—; while (j

!= i);

 

 

}

 

 

 

 

 

 

a. A C Program

 

 

* 3:

for(j = k = 0;

j != i;

j++) k +=

j;

00000802

C7

CLRB

 

 

 

00000803

87

CLRA

 

 

 

00000804

B745

TFR

D,X

 

 

00000806

2005

BRA

*+7

;abs = 080D

00000808

1AE6

LEAK

Df X

 

 

0000080A

C30001

ADDD

#1

 

 

0000080D

BC0800

CPD

$0800

 

 

00000810

26F6

BNE

*-8

;abs = 0808

* 4:

while(j != 0) k += —j;

 

 

00000812

2005

BRA

*+7

;abs = 0819

00000814

830001

SUBD

#1

 

 

00000817

1AE6

LEAK

D,X

 

 

00000819

0474F8

TBNE

D,*-5

 

;abs = 0814

* 5:

do k += j—; while (j != i);

 

 

0000081C

1AE6

LEAK

D,X

 

 

0000081E

09

DEX

 

 

 

0000081F

BC0800

CPD

$0800

 

 

00000822

26F8

BNE

*-6

;abs = 081C

00000824

3D

RTS

 

 

 

b. Assembly Language developed from Part (a)

Figure 9.10.For, While, and Do While Loops

9.4 Loop Statements, Arrays, and Structs

275

In Figure 9.10 a for loop has an initialization expression, shown first in the for list of expressions; a test expression, shown in the middle; and a loop termination expression, shown last:

* 3:

for(j = k = 0; j != i; j++) k += j;

 

CLRB

 

; j in D

 

CLRA

 

 

 

TFR

D, X

; k in X

 

BRA

LI

; do the test before the loop is done once

LO :

LEAX

D, X

; this is the statement that is executed in the loop

 

ADDD

#1

; this is the expression done after each loop is done

LI:

CPD

$0800

; this is the loop test

 

BNE

LO

 

A while loop has a test expression that is executed before the loop is executed once:

* 4:

while(j !=

0) k += — j ;

 

BRA

L3

; do the test first

L2 :

SUED

#1

; these are the two statements

 

LEAX

D,X

; that are executed in the loop

L3 :

TBNE

D,L2

; this is the loop test

A do while loop has a test expression that is executed after the loop is executed:

* 5:

 

do k += j—; while (j != i);

L4 :

LEAX D, X

; these are the two statements

 

DEX

 

; that are executed in the loop

 

CPD

$0800

; this is the loop test

 

BNE

L4

 

Figure 9.11 illustrates nested for loops and the two-dimesional array index addressing mechanism. This example shows how loop statements can themselves be loops, in a nested loop construction, and how optimizing compilers make loops more efficient. The outer for loop, for (i = sum = 0 ; i < 10; i++) is encoded asan initialization:

CLRA

 

; generate 0

CLRB

 

; in high and low bytes

STD

$08 IE

; store to clear sum

STAB

1, SP

; store to clear i

and by the outer loop termination:

INC

1, SP

; count up

LDAA

1, SP

; get the variable to be tested

CMPA

#10

; compare against 10

BCS

*-40

; loop as long as i is less than 10

CMPA

#3

; check if another iteration is to be done

BCS

*-30

; if so, branch to the instruction following the initialization

276

Chapter 9 Implementation of C Procedures

unsigned char a[10][3]; int sum; main() { unsigned char i, j;

for(i = sum= 0 ; i < 10; i++) for(j=0; j < 3; j++)

sum +=£ a[i][j];

>

a.A C Program

4:main() { unsigned char i," j;

0000095B 3B

PSHD

5:for(i = sum = 0; i < 10; i++)

0000095C C7

CLRB

 

 

0000095D

87

CLRA

 

 

0000095E

7C081E

STD

$081E

 

00000961

6B81

STAB

1,SP

 

6:

 

for(j = 0;

j < 3;

j++) sum += a[i][j];

00000963

6980

CLR

0,SP

 

00000965

E681

LDAB

1,SP

 

00000967

87

CLRA

 

 

00000968

CD0003

LDY

#3

 

0000096B

13

EMUL

 

 

0000096C

B745

TFR

D,X

 

0000096E

E680

LDAB

0,SP

 

00000970 87

CLRA

 

 

00000971

1AE6

LEAK

D,X

 

00000973

E6E20800

LDAB

2048,X

00000977 F3081E

ADDD

$081E

 

0000097A

7C081E

STD

$081E

 

0000097D

6280

INC

0,SP

 

0000097F A680

LDAA

0,SP

 

00000981

8103

CMPA

#3

 

00000983

25EO

BCS

*-30

;abs = 0965

5:for(i = sum = 0; i < 10;i++)

00000985

6281

INC

1,SP

00000987

A681

LDAA

1,SP

00000989

810A

CMPA

#10

0000098B

25D6

BCS

*-40 ;abs = 0963

7: }

 

 

 

0000098D

30

PULX

 

0000098E

3D

RTS

 

b. AssemblyLanguage developed from Part (a)

Figure 9.11. Array ManipulationProgram

278

Chapter 9 Implementation of C Procedures

struct spiDevice{

unsigned int spie:l,spe:l,swom:l,mstr:lfcpol:lrcpha:l,ssoeil, lsbf:l;

} *spiPtr = (struct spiDevice *)OxdO; #define spi (*spiPtr)

raain() { spi.spe = 1;

do ; while(spi.spe); }

 

 

 

a. A C Program

 

0000095B

3B

PSHD

 

 

0000095C

FE0800

LDX

spiPtr

 

0000095F

6E80

STX

0,SP

 

00000961

OC0040

BSET

0,X,#64

 

00000964

EE80

LDX

0,SP

 

00000966

OE0040FA

BRSET

0,X,#64,*-6

;abs = 0964

0000096A

30

PULX

 

 

0000096B

3D

RTS

 

 

b. Assembly Language developed from Part (a)

Figure 9.13. A Program Setting and Testing a Bit

The do while statement in Figure 9.13a tests the condition after the loop is executed at least once, but it tests the result of the loop's activities. This is very useful in I/O software because it lets you get data within the statement and test the result in the conditional expression, which is not executed until the statement is executed at least once. See Figure 9.13. The program sets a bit of a struct and tests it repeatedly until it is cleared (by hardware). It is compiled into assembly language shown in Figure 9.13b. The struct definition shown below merely defines accesses using the pointer spiPtr. The elements can be accessed using "arrow" notation. For instance the bit spe can be

set using spiPtr->spe

= 1; However, by declaring #define spi (*spiPtr), the

expression spi. spe =

1; can be used instead. This is encoded into assembly language

using the BSETinstruction:

BSET 0, X, #6 4

; set bit 6 of location pointed to by X (the spi port)

The statement do ; while (spi. spe); is implemented with

BRSET 0, X,#6 4 , * - 6 ; wait while bit 6 of location OxDO is 1

Generally, if the bitfield is more than one bit, data to be inserted will have to be shifted to the correct bit position, and masked parts of it are ORed with masked parts of bits in other fields, to be written into the memory. This code looks like the code for statement lui = (lui « 3) + (lui « 1) + Isc - ' 0 ' ; that westudied at theend of Section 9.2. Data read from such a bitfield will have to be shifted and masked in like manner.

280

Chapter 9 Implementation of C Procedures

int a;

 

void main() { int

b; b = power(&a, 2); }

 

 

int

power(int

*i,

unsigned

char

j ) { int

n ~ 1;

 

 

while(

j—

) n = n

* *i;

return

n;

 

}

 

 

 

 

 

 

 

a. A C Procedurecalling a Subroutine

 

 

00000976

CC0800

LDD

#2048

 

 

 

00000979

3B

PSHD

 

 

 

 

0000097A

C602

LDAB

#2

 

 

 

0000097C

07DD

BSR

*-33

;abs = 095B

 

0000097E

3A

PULD

 

 

 

 

0000097F

3D

RTS

 

 

 

 

b. Assembly Language for the Calling Procedure in Part (a)

0000095B CE0001

LDX

#1

 

4:

while( j— )

n = n * *i;

 

0000095E

B710

TFR

B,A

 

00000960 200B

BRA

*+13

;abs = 096D

00000962 ED82

LDY

2,SP

 

00000964 36

PSHA

 

 

00000965

EC40

LDD

0,Y

 

00000967 B756

TFR

X,Y

 

00000969

13

EMUL

 

 

0000096A

B745

TFR

D,X

 

0000096C

32

PULA

 

 

0000096D

36

PSHA

 

 

0000096E

43

DECA

 

 

0000096F

E6BO

LDAB

1,SP+

 

00000971

26EF

BNE

*-15

;abs = 0962

5:return n;

00000973

B754

TFR

X,D

00000975

3D

RTS

 

c. Assembly Language for the Called Procedure in Part (a)

Figure 9.14. A Subroutine to Raise a Number to a Power

SP-> inside the subroutine

Figure 9.15. Stack for power Procedure

9.6 Examples from Character String Procedures

283

3: char *strchr(char *str, int chr){

 

0000088A 3B

PSHD

 

4:while (*str) {

QOG0088B 200B

BRA *+13 ;abs = 0898

5:if(*str == chr) return (str);

0000088D

B715

SEX

B,X

0000088F

AE80

CPX

0,SP

00000891

2711

BEQ

*+19 ;abs = 08A4

6:-M-str;

00000893

EE84

LDX

4,SP

00000895

08

INX

 

00000896

6E84

STX

4,SP

4:while (*str) {

00000898

EE84

LDX

4,SP

0000089A

E600

LDAB

0,X

0000089C

26EF

BNE

*-15 ?abs = 088D

8:if(*str == chr) return str;

0000089E B715

SEX

B,X

 

000008AO AE80

CPX

0,SP

 

000008A2

2603

BNE

*+5

;abs = 08A7

000008A4 EC84

LDD

4,SP

 

000008A6

8FC787

CPS

#51079

 

10: }

 

 

 

 

000008A9

30

PULX

 

 

000008AA

3D

RTS

 

 

Figure 9.18. The Strchr Procedure

The procedure str chr searches for a character in a null-terminated string. See Figure 9.18. The first argument specifies the string. The second argument is a character. The procedure searches the string for a matching character; if it finds the character, it returns the address of the character in the string, otherwise it retuns a null (0).

We now show strncpy which is used to copy characters from and to a nullterminated string. See Figure 9.19. We show the calling routine for this example to illustrate the passing of more than three arguments. The main procedure calls the strncpy procedure with three arguments. Notice how arguments are pushed in order or their appearance from left to right, so the leftmost string, pushed first, is at 8,SP inside strncpy. You should step through the while loop to see how each C statement is compiled into assembly language. Note, however, that the pointers keep getting reloaded into X and Y registers from their local variable storage locations. You can do a lot better by writing the program in assembler language. But you can use this code, produced by the Hiware C++ compiler, as a starting point for a tightly coded assembler language program.

The procedure strncmp compares characters in two null-terminated strings, specified by the first two arguments, up to a number of characters specified in the third argument. See Figure 9.20. Observe the condition used to execute the while loop. If any of the three conditions are false, the subroutine terminates.

284

Chapter 9 Implementationof C Procedures

char *strncpy(char *str_d,char *str_s,int count){char *sd = str d;

0000088A

3B

PSHD

 

 

0000088B

3B

PSHD

 

 

0000088C

EC88

LDD

8,SP

 

QQOGQ88E

6C82

STD

2,SP

 

51 while(count—) {

 

 

 

00000890

201A

BRA

*+28

;abs = 08AC

6:if(*str_s) *str__d++ = *str_s++;

00000892

EE86

LDX

6,SP

 

00000894 E600

LDAB

0,X

 

00000896

270E

BEQ

*+16

;abs = 08A6

00000898

EE88

LDX

8,SP

 

0000089A

ED86

LDY

6,SP

 

0000089C

E670

LDAB

1,Y+

 

0000089E

6B30

STAB

1,X+

 

000008AO

6E88

STX

8,SP

 

000008A2

6D86

STY

6,SP

 

000008A4

2006

BRA

*+8

;abs = 08AC

7:else *str_d++ = '\0';

000008A6 EE88

LDX

8,SP

000008A8

6930

CLR

1,X+

000008AA

6E88

STX

8,SP

5:while(count—) {

000008AC EE80

'LDX

0,SP

000008AE

191F

LEAY

-1,X

000008BO

6D80

STY

0,SP

000008B2

0475DD

TBNE

X,*-32 ;abs = 0892

9:return (sd);

000008B5

EC82

LDD

2,SP

 

10: }

 

 

 

 

000008B7

1B84

LEAS

4,SP

 

000008B9

3D

RTS

 

 

13: void main()

{ strncpy(sl,

s2, 5);

 

000008BD

CC080B

LDD

#2059

; this is si

000008CO

3B

PSHD

 

 

000008C1

CE0800

LDX

#2048

; this is s2

000008C4

34

PSHX

 

 

000008C5

C605

LDAB

#5

; this is the rightmost argument

000008C7

87

CLRA

 

 

000008C8

07CO

BSR

*-62

;abs = 088A

000008CA

1B84

LEAS

4,SP

 

15: }

 

 

 

 

000008D2

3D

RTS

 

 

Figure 9.19. The Strncpy Procedure

9.6 Examples from Character String Procedures

285

4: int

strncmp(char *strl, char *str2, int count) {

0000088A

6CAE

STD 2,-SP

5:if (!count) return 0;

0000088C

2618

BNE

*+26

;abs

=

08A6

0000088E

C7

CLRB

 

 

 

 

0000088F

87

CLRA

 

 

 

 

00000890

203B

BRA

*+61

;abs

=

08CD

7:if (*strl != *str2) break;

00000892

EE86

LDX

6,SP

 

00000894

E600

LDAB

0,X

 

00000896

EE84

LDX

4,SP

 

00000898

E100

CMPB

0,X

 

0000089A

261F

BNE

*+33

;abs = 08BB

8:++strl; ++str2;

0000089C

EE86

LDX

6,SP

0000089E

08

INX

 

0000089F

6E86

STX

6,SP

000008A1 EE84

LDX

4,SP

000008A3

08

INX

 

000008A4

6E84

STX

4,SP

6:while(count— &&*strl && *str2 ){

000008A6 EE80

LDX

0,SP

 

000008A8

191F

LEAY

-1,X

 

000008AA

6D80

STY

0,SP

 

000008AC

04450C

TBEQ

X,*+15

;abs = 08BB

000008AF

EE86

LDX

6,SP

 

000008B1

E600

LDAB

0,X

 

000008B3

2706

BEQ

*+8

;abs = 08BB

000008B5 EE84

LDX

4,SP

 

000008B7

E600

LDAB

0,X

 

000008B9

26D7

BNE

*-39

;abs = 0892

10:return (*strl - *str2);

000008BB

EE86

LDX

6,SP

000008BD

E600

LDAB

0,X

000008BF

B714

SEX

BfD

000008C1

EE84

LDX

4,SP

000008C3

3B

PSHD

 

000008C4

E600

LDAB

0,X

000008C6

B715

SEX

B,X

000008C8

34

PSHX

 

000008C9

EC82

LDD

2,SP

000008CB

A3B3

SUED

4,SP+

11: }

 

 

 

000008CD

30

PULX

 

000008CE

3D

RTS

 

Figure 9.20. The Strncmp Procedure

288 Chapter 9 Implementation of C Procedures

9. Global variables are declared as struct { unsigned int alpha: 3, beta:?, gamma: 6 } *p; int i;. A struct with bit fields is packed from leftmost bit forthe first field named on the left, through consecutive fields, toward the right. Write a shortest program segment to execute each of the following C statements.

 

a. i = p->alpha;

 

 

 

b. p->beti =- i;

c.p->alpha

= p->gamma;

10.

Write a shortest program segment to execute each of the following C statements,

 

a. gui =

(gui & Oxc7ff)

+ ((Isc « 11)

& 0x3800);

 

 

 

 

b. lux

=

(lui & Oxffc?)

\

((gsc « 3) & 0x38);

 

 

 

 

 

c. lui

=

(lui & Oxc7c7)

+

((gsc«3)&0x38)

\

((Isc«ll)&0x3800);

11.

Write a shortest program segment to execute each of the following C statements,

 

a. guc

= gui

>= lac

; «

 

 

 

 

 

 

 

 

 

 

 

 

 

 

b. luc

= lui

< gsc

;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

c. lui

=

(gui >= Isc)

\ \

(lui

< gsc) ;

 

 

 

 

 

 

 

12.

Write a shortest program segment to execute each of the following C statements.

 

a. if{

gui

>= Isc

)

lui++;

 

 

 

 

 

 

 

 

 

 

 

b. if(

!

(

gui A

Isc)

)

lui

*= 10;

 

 

 

 

 

 

 

 

 

c. i f ( (

gui >= Isc ) & &

( !

(

(gui A Isc)

& gsc) )

)

lui

A= gui;

13.

Write a shortest program segment to execute each of the following C statements.

 

a. if((

gui

 

<= Isc

) | j (

gui

>=( Isc

+ 7 ) ) )

 

lui++;

 

 

 

 

b. if(

(

gui

> Isc)

&&

(

gui

< (Isc +

3)

)

)

lui

*=

10;

 

 

c. i f ( (

gui

 

>= 0

) && (

Isi

<

0 )

&& (

gui

>

Isi

)

) lui

"= gui;

14.Write the case statement below according to the conventions of Figure 9.9a. switch(guc){case 2: gui = -1; break;case 4:Isc = -1;default:Isi = -1;}

15.Repeat Problem 14 according to the conventions of Figure 9.9b.-

16.Rewrite the assembly-language program of Figure 9.1Ib for a main program, like

Figure 9.11 a, in which the declaration int statement sum += a[i][j]; is replaced by if

sum; is replaced by int k;, and the (k > a[i][j] ) k = a[i][j];

17. Write the C program and the resulting assembly-language program that transposes a two-dimensional matrix of size 4 by 4, following the approach of Figure 9.11.

18. Write the C program and the resulting assembly-language program that stays in a do while loop as long as both bits 7 and 6 of the byte at location $dOare zero, following the approach of Figure 9.13b.