
- •Acknowledgments
- •About the Author
- •1.1 Basic Computer Structure
- •1.3 A Few Instructions and Some Simple Programs
- •2 The Instruction Set
- •3.1 Op Code Byte Addressing Modes
- •4.2 Assembler Directives
- •4.3 Mechanics of a Two-Pass Assembler
- •4.6 Summary
- •5.1 Cross Assemblers and Downloaders
- •5 Problems
- •6.3 Passing Arguments by Value, Reference, and Name
- •7 Arithmetic Operations
- •7.2 Integer Conversion
- •8 Programming in C and C++
- •8.1 Compilers and Interpreters
- •9 Implementation of C Procedures
- •9.2 Expressions and Assignment Statements
- •9.4 Loop Statements, Arrays, and Structs
- •10 Elementary Data Structures
- •10.1 What a Data Structure Is
- •11.4 Synchronization Hardware
- •12.4 The 68300 Series
- •A2.1 Loading HiWare Software
- •A2.2 Opening the HiWare Toolbox
- •A2.3 Running Examples From the ManualProgramFolder
- •A2.6 POD-Mode BDM Interface
- •Index

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.

