- •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
9.2 Expressions and Assignment Statements |
257 |
The input and output statements use page-zero addressing, which provides improved static and dynamic efficiency over direct adddressing. Note that the MOVB instruction is not useful for accessing these I/O ports, because there is no page-zero address option in MOVB. The LDAB and STAB instructions above are more efficient than a MOVB instruction.
The assignment of I/O ports to global variable names should be written and executed before true global variables are assigned, because the origin will be set to the beginning of RAM (at $800) to assign true global variables. The declaration of globally defined I/O ports is often put in an #include file, which is inserted in a program before globals are defined in the program.
9.2 Expressions and Assignment Statements
In this section, we illustrate how operators are used in expressions. We will look at addition and subtraction statements that use same-width and different-width operands in a discussion of upcasting and downcasting. We will then study statements that use logical and arithmetic operators. We will carefully consider the increment and decrement operators and then look at expressions that save temporary results on the hardware stack.
The program in Figure 9.2a has several local and global variables, some of which are signed and others of which are unsigned, and some of which are 8-bit and others of which are 16-bit. Figure 9.2b shows assembly language developed from this program. Observe that each variable's name is an abbreviation of its characteristics; gsi is a global signed integer.
Many C statements are easily and efficiently translated into assembly language. This
is especially true when all the variables |
in a statement are 8-bit char or unsigned |
|||||||
char |
variables or when all the variables in a statement are 16-bit int or unsigned |
|||||||
int |
variables. Assume the following statements |
are written in Figure 9.2a's main. |
||||||
Figure 9,2's statement |
gsi |
= lui + 12; |
is easily encoded as |
|
||||
|
LDX |
0, SP |
; get 16-bit local variable |
lui |
|
|||
|
LEAX |
12, X |
; add 12 (note that this is shorter than addd #12) |
|||||
|
STX |
$0801 |
; put into 16-bit global variable gsi |
|
||||
and similarly the statement |
guc |
= Isc |
- 33; |
is simply encoded as |
|
|||
|
LDAB |
2, SP |
; get 8-bit local variable Isc |
|
||||
|
SUBB |
#33 |
; subtract 33 |
|
|
|
||
|
STAB |
$0800 |
; put into 8-bit global variable guc |
|
||||
If a statement gets an int |
variable and writes a char variable, the source is truncated |
|||||||
when it is read. Figure 9.2's statement guc |
= lui |
+ 9; |
is encoded as |
|
||||
|
LDAB |
1, SP |
; get low byte of 16-bit local variable lui |
|||||
|
ADDB |
#9 |
|
; add 9 |
|
|
|
|
|
STAB $0800 |
; put into 8-bit global variable guc |
|
|||||
An optimizing compiler can change the instruction ADDD #9 |
to ADDB #9 |
|||||||
because the result will not be altered (reducing the precision is called |
downcasting). |
|||||||
9.2 |
Expressions and Assignment Statements |
|
|
259 |
|||
|
If a statement gets a char variable and writes an int or unsigned |
int |
variable, |
||||
the result is sign extended when it is read. Figure 9.2's statement gsi = |
gsi |
+ Isc; |
|||||
or equivalently gsi |
|
+= isc ,•is simply encoded as |
|
|
|
||
|
LDAA |
2, SP |
; get 8-bit global variable Isc |
|
|
|
|
|
SEX |
|
A, D |
; upcast from char to int or unsigned |
int |
|
|
|
ADDD |
$08 01 |
; add in 16-bit global variable gsi |
|
|
||
|
STD |
|
$0801 |
; put into 16-bit global variable |
gsi |
|
|
But if a statement gets an unsigned char variable and writes an int |
or unsigned |
||||||
int |
variable, the high byte is cleared before the unsigned |
char variable is read. |
|||||
Figure 9.2's statement lui = |
guc - 17; is encoded as |
|
|
|
|||
|
LDAB $0800 |
; get 8-bit global variable guc saved earlier |
|
|
|||
|
CLRA |
|
|
; upcast from unsigned char to int |
or unsigned |
int |
|
|
SUED |
#17 |
; subtract 17 |
|
|
|
|
|
STD |
0, SP |
; put into 16-bit global variable lui |
|
|
|
|
You should observe that the declaration char or int affects the instruction data length, and char and unsigned char determine whether, on upcasting, the 8-bit data is sign extended with an SEX instruction or filled with zeros using a CLRA instruction.
The previous examples should indicate to the C programmer how to decide how a
variable is |
to be type cast. If its range of values is 0 to 127, declare it to |
be an |
unsigned |
char, because upcasting is done with a short CLRA instruction rather than a |
|
longer SEX |
instruction. If its range is 0 to 256, declare it to be an unsigned |
char, |
but if the range is -128 to 127, declare it a char, to save space and time. Otherwise declare it to be int.
To discuss how common operators are handled, we use the following main as an example; it merely ANDs, ORs, multiplies, and divides some variables. Figure 9.3a's program is compiled into the assembly-language program in Figure 9.3b.
Logical bit-by-bit ANDing is illustrated in Figure 9.3 by the expression Isc = lsc& guc; or equivalentlyby Isc &= guc;, which is realized by
LDAA |
2, SP |
; get local variable Isc |
ANDA $0800 |
; AND with global variable guc |
|
STAA |
2, SP |
; put into local variable Isc |
However, if one of the operands is constant, the BCLR instruction can be used. The expression in Figure 9.3, Isc = lsc& 0x12;,or equivalently Isc &= 0x12; is realized by
BCLR 2, SP, #23 7 ; ANDlocal variable Isc with inverted constant 0x12
Note that the complement of the constant is used in the operand of BCLR. Logical bit-
by-bit ORing is illustrated |
in Figure 9.3 by the expression gsi - gsi | lui; or |
||
equivalently bygsi |= lui;, which isrealizedby |
|
||
LDD |
$0801 |
; get global variable gsi |
|
ORAA |
1, SP |
; OR with high byte of local variable |
lui |
ORAB |
0, SP |
; OR with low byte of local variable |
lui |
STD |
$0801 |
; put into global variable gsi |
|
260 |
|
|
|
|
Chapter 9 |
Implementation of C Procedures |
|
unsigned |
char |
guc; |
int |
gsi; |
|
|
|
main(){ |
char |
Isc; |
unsigned |
int lui; |
|
|
|
Isc |
= Isc |
&guc; |
Isc &= 0x12; |
gsi = gsi |
| lui; |
||
gsi |
= gsi |
& 0x1234; lui |
= Isc * guc; lui |
= lui / guc; |
|||
}
a.A C program
4:main(){ char Isc; unsigned int lui;
0000095B 1B9D |
LEAS -3,SP |
5:Isc = Isc & guc; Isc &= 0x12;
0000095D |
A682 |
LDAA |
2, SP |
0000095F B40800 |
ANDA |
$0800 |
|
00000962 |
6A82 |
STAA |
2,SP |
00000964 |
OD82ED |
BCLR |
2,SPf#237 |
6:gsi = gsi|lui; gsi = gsi|0x1234;
00000967 |
FC0801 |
LDD |
$0801 |
0000096A |
EA81 |
GRAB |
1,SP |
0000096C AA80 |
ORAA |
0,SP |
|
0000096E |
7C0801 |
STD |
$0801 |
00000971 |
1C080112 |
BSET |
$0801,#18 |
00000975 |
1C080234 |
BSET |
$0802,#52 |
7:lui = Isc *guc;
00000979 |
A682 |
LDAA |
2,SP |
0000097B B706 |
SEX |
ArY |
|
0000097D |
F60800 |
LDAB |
$0800 |
00000980 |
87 |
CLRA |
|
00000981 |
13 |
EMUL |
|
00000982 |
6C80 |
STD |
0,SP |
7:lui = lui / guc;
00000984 F60800 |
LDAB |
$0800 |
|
00000987 |
87 |
CLRA |
|
00000988 |
B745 |
TFR |
D,X |
0000098A ECB1 |
LDD |
0,SP |
|
0000098C |
1810 |
IDIV |
|
0000098E |
6E80 |
STX |
0,SP |
8: } |
|
|
|
00000990 |
1B83 |
LEAS |
3,SP |
00000992 |
3D |
RTS |
|
b. Assembly Language Generated by Part (a)
Figure 93. A C Program with SomeOperators
However, if one of the operands is constant, BSET can be used. The expression gsi =
gsi | 0x1234; orequivalently gsi |
|= 0x1234; isrealizedby |
|
BSET |
$0801,#18 |
;OR high byte of global variable gsi with Ox 12 |
BSET |
$0802, #52 |
; OR global variable low byte gsi with 0x34 |
262 |
|
Chapter 9 Implementation of C Procedures |
LDX |
$0801 |
;getgsi |
INX |
|
; add 1 |
STX |
$0801 |
; put it back |
and the statement lui—; in Figure 9.4 is implemented |
||
LDX |
1, SP |
; get lui |
DEX |
|
; subtract 1 |
STX |
1, SP |
; put it back |
When the increment or decrement operator appears in a larger expression, the initial or final value of the variable used in the outer expression depends on whether the pair of "+" or "-" signs appearsbefore or after the variable. Isc = ++ guc; is implemented
unsigned char guc; int gsi; main{){ char Isc; unsigned int lui;
guc++; Isc—; gsi++; lui—; Isc = ++guc; Isc = guc++;
}
a.A C Program
4:main(){ char Isc; unsigned int lui;
0000095B 1B9D |
LEAS -3,SP |
5:guc++;
0000095D |
720800 |
INC |
$0800 |
6: |
Isc—; |
|
|
00000960 |
6380 |
DEC |
0,SP |
7:gsi++;
00000962 |
FE0801 |
LDX |
$0801 |
00000965 |
08 |
INX |
|
00000966 |
7E0801 |
STX |
$0801 |
8:lui—;
00000969 |
EE81 |
LDX |
1,SP |
0000096B 09 |
DEX |
|
|
0000096C |
6E81 |
STX |
1,SP |
9:Isc = ++guc;
0000096E |
720800 |
INC |
$0800 |
00000971 |
B60800 |
LDAA |
$0800 |
00000974 |
6A80 |
STAA |
0,SP |
10:Isc = guc++;
00000976 |
A680 |
LDAA |
0,SP |
00000978 |
720800 |
INC |
$0800 |
0000097B |
6A80 |
STAA |
OrSP |
0000097D |
1B83 |
LEAS |
3,SP |
0000097F |
3D |
RTS |
|
b. Assembly Language Generatedby Part (a)
Figure 9.4. A C Program with Incrementing andDecrementing
264 |
Chapter 9 Implementation of C Procedures |
unsigned char guc; int gsi;
main(){ char Isc; unsigned |
int lui; |
|
lui |
-= Isc; lui = (lui |
& Oxfc7f) j ((Isc « 7) & 0x380); |
lui |
= (lui « 3) + (lui |
« 1) + Isc - '0' ; |
}
a.C Program
4:main(){ char Isc; unsigned int lui; lui -= Isc;
0000095B |
1B9D |
LEAS |
-3,SP |
0000095D A682 |
LDAA |
2,SP |
|
0000095F B706 |
SEX |
A,Y |
|
00000961 EC80 |
LDD |
0,SP |
|
00000963 |
35 |
PSHY |
|
00000964 |
A3B1 |
SUBD |
2,SP+ |
00000966 |
6C80 |
STD |
0,SP |
6: |
lui = (lui |
& Oxfc7f)| |
((Isc « 7) & 0x380); |
00000968 |
3B |
PSHD |
|
00000969 C680 |
LDAB |
#128 |
|
0000096B |
87 |
CLRA |
|
0000096C |
35 |
PSHY |
|
0000096D |
13 |
EMUL |
|
0000096E C480 |
ANDB |
#128 |
|
00000970 |
8403 |
ANDA |
#3 |
00000972 |
3B |
PSHD |
|
00000973 |
EC84 |
LDD |
4,SP |
00000975 |
C47F |
ANDB |
#127 |
00000977 |
84FC |
ANDA |
#252 |
00000979 |
AA81 |
ORAA |
1,SP+ |
0000097B |
EA81 |
GRAB |
0,SP+ |
0000097D |
6C82 |
STD |
2,SP |
7:lui = (lui « 3) + (lui « 1) + Isc -'0 ' ;
0000097F |
59 |
ASLD |
|
00000980 |
59 |
ASLD |
|
00000981 |
59 |
ASLD |
|
00000982 |
B745 |
TFR |
D,X |
00000984 |
EC82 |
LDD |
2,SP |
00000986 |
59 |
ASLD |
|
00000987 |
1AE6 |
LEAX |
D,X |
00000989 |
B754 |
TFR |
X,D |
0000098B |
E380 |
ADDD |
0,SP |
0000098D |
830030 |
SUBD |
#48 |
00000990 |
6C84 |
STD |
4,SP |
00000992 |
1B87 |
LEAS |
7,SP |
00000994 |
3D |
RTS |
|
b. Assembly Language Generatedby Part (a)
Figure 9.5. A C Program with ORing, ANDing and Shifting
266 |
Chapter 9 Implementation of C Procedures |
unsigned char guc; int gsi; |
|
|
|||
main{){ |
char |
Isc; unsigned int lui; |
|
|
|
guc |
= Isc |
> -3; |
Isc = lui > 5; lui |
= gsi |
>= 0; |
gsi |
= lui |
>= 0; |
gsi = Isc — 0; |
Isc = |
(gsi & 4) == 0; |
1
a.A C Program
5:guc = Isc > -3; Isc = lui > 5;
0000095B A6AD |
LDAA |
3,-SP |
|
|
0000095D |
81FD |
CMPA |
#253 |
|
0000095F |
2E02 |
BGT |
*+4 |
;abs = 0963 |
00000961 |
87 |
CLRA |
|
|
00000962 |
8F8601 |
CPS |
#34305 |
|
00000965 |
7A0800 |
STAA |
$0800 |
|
00000968 |
EC81 |
LDD |
1,SP |
|
0000096A |
8C0005 |
CPD |
#5 |
|
0000096D |
2202 |
BHI |
*+4 |
;abs = 0971 |
0000096F |
87 |
CLRA |
|
|
00000970 |
8F8601 |
CPS |
#34305 |
|
00000973 |
6A80 |
STAA |
0,SP |
|
7:lui = gsi >= 0;
00000975 |
FC0801 |
LDD |
$0801 |
|
00000978 2A02 |
BPL |
*+4 |
;abs = 097C |
|
0000097A |
C7 |
CLRB |
|
|
0000097B |
8FC601 |
CPS |
#50689 |
|
0000097E |
87 |
CLRA |
|
|
0000097F |
6C81 |
STD |
1,SP |
|
8s |
gsi = lui >= 0; |
|
|
|
00000981 |
C601 |
LDAB |
#1 |
|
00000983 |
87 |
CLRA |
|
|
00000984 |
7C0801 |
STD |
$0801 |
|
9:gsi = Isc == 0;
00000987 A680 |
LDAA |
0,SP |
|
|
00000989 |
2702 |
BEQ |
*+4 |
,-abs = 098D |
0000098B |
C7 |
CLRB |
|
|
0000098C |
8FC601 |
CPS |
#50689 |
|
0000098F |
87 |
CLRA |
|
|
00000990 |
7C0801 |
STD |
$0801 |
|
10:Isc = (gsi& 4) == 0;
00000993 |
1F08020402 |
BRCLR |
$0802,#4,*+7 |
;abs = 099A |
00000998 |
87 |
CLRA |
|
|
00000999 |
8F8601 |
CPS |
#34305 |
|
0000099C 6AB2 |
STAA |
3,SP+ |
|
|
b. Assembly Language Generated by the body of Part (a)
Figure 9.6. A Program with Boolean Operators
268 |
|
|
Chapter 9 Implementation of C Procedures |
Certain bit tests can often use BRSET |
or BRCLR branches. In Figure 9.6, the |
||
expression Isc = (gsi & 4) |
== 0; results in the following code: |
||
BRCLR |
$0802, #4 , *+2 |
;if bit 4 is not zero then |
|
CLRA |
|
; clear result |
|
GPS |
#34305 |
; skip, or set result to 1 |
|
STAA |
3, SP+ |
; put result in lui and deallocate local variables |
|
The Boolean result of the test, a value of 1 (T) or a 0 (F), is actually not usually generated but may be used to branch to a different location. For instance if {lui > 5) results in the following code:
LDD |
1, SP |
; get 16-bit variable lui |
CPD |
#5 |
; if less than 5 as an unsigned number |
BLS |
L |
; branch around the expression if lui is higher than 5 |
Simple conditional expressions of the form if then, full conditionals of the form if then else, and extended conditionals of the form if then else if then else if then , . . else, use conditional expression operators. In the last expression, the else if part can be repeated as many times as needed, and the last part can be an optional else. Variables are compared using relational operators ( > and < ), and these are combined using logical operators (&&). We give examples of common simple conditionals first.
The C program in Figure 9.7a is compiled into the assembly language program shown in Figure 9.7b. A statement if (! Isc) guc = 0; or equivalently if (Isc ==
0) guc = 0; is encoded as |
|
|
LDAA |
3, -SP |
; allocate and set condition codes for variable Isc |
BNE |
*+5 |
; if nonzero, skip over next instruction |
CLR |
$0800 |
;otherwise, if zero, clear variable guc |
Where the condition applies to a complex expression of many statements, the branch instructions can be converted to long branch instructions. For instance,
|
|
if (gsi |
< 5) { ... /* many instructions */} |
can be implemented |
|
|
|
|
LDD |
$0801 |
;get variable gsi |
|
CPD |
#5 |
; if greater than or equal to 5 as an unsigned number |
|
LBGE |
LI |
; then skip over next several instructions |
|
|
|
; many instructions generated between { } appear here |
LI: |
EQU |
* |
; located after the latter} matching the if statement's { |
A simple C compiler can always implement the conditional operation using the long branch instructions like LBHS, but an optimizing C compiler will get the size of the branch offset. It uses a long branch instruction when the label cannot be reached by the corresponding shorter branch instruction.
9.3 Conditional Statements |
269 |
unsigned char guc; int gsi; main(){ char Isc; unsigned int lui;
if(lsc == 0) guc = 0;
if(gsi < 5) { ... /* many instructions */ } if(Isc + guc) gsi = 0;
if(guc < 5) Isc = 0; else Isc = 9;
}
a.A C Program
4: main(){ char Isc; unsigned int lui;if(Isc == 0) guc = 0;
0000095B A6AD |
LDAA |
3,-SP |
|
|
0000095D |
2603 |
BNE |
*+5 |
;abs = 0962 |
0000095F |
790800 |
CLR |
$0800 |
|
6: |
if(gsi < 5) { /* many instructions */ lui =0; } |
|||
00000962 |
FC0801 |
LDD |
$0801 |
|
00000965 |
8C0005 |
CPD |
#5 |
|
00000968 |
2C04 |
BGE |
*+6 |
;abs = 096E |
0000096A |
C7 |
CLRB |
|
|
0000096B |
87 |
CLRA |
|
|
0000096C |
6C81 |
STD |
1,SP |
|
7:if(Isc + guc)gsi = 0;
0000096E |
A680 |
LDAA |
0,SP |
00000970 |
B704 |
SEX |
A,D |
00000972 |
B745 |
TFR |
D,X |
00000974 |
F60800 |
LDAB |
$0800 |
00000977 |
87 |
CLRA |
|
00000978 |
1AE6 |
LEAK |
D,X |
0000097A |
044504 |
TBEQ |
X,*+7 ,-abs = 0981 |
0000097D |
C7 |
CLRB |
|
0000097E |
7C0801 |
STD |
$0801 |
8:if(guc < 5) Isc = 0; else Isc = 9;
00000981 |
B60800 |
LDAA |
$0800 |
|
00000984 |
8105 |
CMPA |
#5 |
|
00000986 |
2404 |
BCC |
*+6 |
;abs = 098C |
00000988 |
6980 |
CLR |
0,SP |
|
0000098A |
2004 |
BRA |
*+6 |
;abs = 0990 |
0000098C |
C609 |
LDAB |
#9 |
|
0000098E |
6B80 |
STAB |
0,SP |
|
9: } |
|
|
|
|
00000990 |
1B83 |
LEAS |
3,SP |
|
00000992 |
3D |
RTS |
|
|
b. Assembly Language Generated by Part (a)
Figure 9.7. A Program with If-Then Expressions
270 |
Chapter 9 Implementation of C Procedures |
|||
unsigned char alpha, beta , gamma, delta, epsilon, zeta; |
||||
main ( ) { |
|
|
|
|
if((alpha |
< 5)&&(beta = = 0 ) ) |
gamma |
= |
0; |
if((alpha |
< 5)||(beta = = 0 ) ) |
gamma |
= |
0; |
if(alpha |
!= 0) beta = 10; else if(gamma — 0) delta++; |
|||
else if((epsilon != 0)&&(zeta==l)) |
beta=beta « 3; else beta=0; |
|||
}
a.A C Program
6:if((alpha < 5)&&(beta == 0)) gamma = 0;
0000095B |
B60800 |
LDAA |
$0800 |
|
0000095E |
8105 |
CMPA |
#5 |
|
00000960 |
2C08 |
BGE |
*-t-10 |
;abs = 096A |
00000962 |
B60801 |
LDAA |
$0801 |
|
00000965 |
2603 |
BNE |
*+5 |
;abs = 096A |
00000967 |
790802 |
CLR |
$0802 |
|
7:if((alpha < 5)|[(beta == 0)) gamma = 0;
0000096A |
B60800 |
LDAA |
$0800 |
|
0000096D |
8105 |
CMPA |
#5 |
|
0000096F |
2D05 |
BLT |
*+7 |
;abs= 0976 |
00000971 |
B60801 |
LDAA |
$0801 |
|
00000974 |
2603 |
BNE |
*+5 |
;abs = 0979 |
00000976 |
790802 |
CLR |
$0802 |
|
8:if(alpha 1= 0) beta = 10;
00000979 |
B60800 |
LDAA |
$0800 |
|
0000097C |
2707 |
BEQ |
*+9 |
;abs = 0985 |
0000097E |
C60A |
LDAB |
#10 |
|
00000980 |
7B0801 |
STAB |
$0801 |
|
00000983 |
201C |
BRA |
*+30 |
;abs = 09A1 |
9:else if(gamma == 0) delta++;
00000985 |
B60802 |
LDAA |
$0802 |
|
|
00000988 |
2605 |
BNE |
*+7 |
;abs = |
098F |
0000098A |
720803 |
INC |
$0803 |
|
|
0000098D |
2012 |
BRA |
*+20 |
;abs |
=09A1 |
10:else if((epsilon!=0)&&(zeta==l)) beta=beta«3; else beta=0;
0000098F |
B60804 |
LDAA |
$0804 |
|
00000992 |
270A |
BEQ |
*+12 |
;abs = 099E |
00000994 |
B60805 |
LDAA |
$0805 |
|
00000997 |
042004 |
DBNE |
A,*+7 |
;abs = 099E |
0000099A |
0764 |
BSR |
*+102 |
;abs = OAOO |
0000099C |
2003 |
BRA |
*+5 |
;abs = 09A1 |
0000099E |
790801 |
CLR |
$0801 |
|
b. Assembly Language Generated by Part (a)
Figure 9.8. Assembly Language for a Decision Tree
9.3 Conditional Statements |
271 |
|
An operation result may be in accumulator B or D. It can be tested by the TBEQ or |
||
TBNE instructions.In Figure 9.7, the statement if(lsc + guc) gsi = 0; similarly |
||
encodes as |
|
|
LDAA |
0, SP |
; get value of Isc |
SEX |
A,D |
; upcast to 16 bits |
TFR |
Df X |
; use X as accumulator |
LDAB |
$08 00 |
; get value of guc |
CLRA |
|
; upcast to 16 bits |
LEAX |
D, X |
; add values |
TBEQ |
X, *+7 |
; check value of sum. If zero |
CLRB |
|
; generate a 16-bit zero (A is already clear) |
STD |
$0801 |
; store to clear variable gsi |
In Figure 9.7, the else part of a conditional expression is easily implemented by a |
||
BRA instruction. The statement |
if (guc < 5) Isc = 0; else Isc = 9; encodes as |
|
LDAA |
$08 00 |
; get variable guc |
CMPA |
#5 |
; if greater than or equal to 5 as an unsigned number |
BBS |
*+6 |
; then skip over next instruction (this isBCC) |
CLR |
0, SP |
; otherwise, if zero, clear variable Isc |
BRA |
*+6 |
; now skip over next two instructions |
LDAB |
#9 |
; write 9 into variable Isc |
STAB |
0,SP |
|
A conditional expression can be a logical OR or a logical AND of tests described above. The logical OR test will check each case, from left to right, for a true result, and will execute the statement when it finds the first true result. The logical AND checks each case, from left to right, for a false, and bypasses the statement the first time it finds
a false test. If alpha, |
beta, |
and gamma are signed global char variables, the |
|
statement in Figure 9.8 if ((alpha |
< 5) |
&&(beta = = 0 ) ) gamma = 0; encodes as |
|
LDAA $0800 |
; get variable alpha |
||
CMPA |
#5 |
|
; if less than 5 as a signed number |
BGE |
*+10 |
; then skip to CLR instruction |
|
LDAA |
$0801 |
; if beta is nonzero |
|
BNE |
*+5 |
|
; then skip over next instruction |
CLR |
$0802 |
;if you get here, clear variable gamma |
|
and if ((alpha < 5) | | |
(beta |
= = 0 ) ) |
gamma = 0; is encodedas |
LDAA $0800 |
; get variable alpha |
||
CMPA |
#5 |
|
; if less than 5 as a signed number |
BLT |
*+7 |
|
; then skip to CLR instruction |
LDAA |
$08 01 |
; if beta is nonzero |
|
BNE |
*+5 |
|
; then skip over next instruction |
CLR |
$0802 |
; if you get here, clear variable gamma. |
|
As seen in the previous examples, the ANDing of conditions is affected by branching around the "then" code if either condition is false, and the ORing of conditions is affected by branching to the "then" code if either condition is true.
272 |
Chapter 9 Implementation of C Procedures |
Many else if expressions can |
be inserted between an if expression and the final |
else expression. The branch instructions jump out of a statement that is executed to the statement beyond the final else statement. Moreover, the final else expression may be omitted. Obviously, one can have more than two OR or AND tests, and one can nest OR tests within AND tests, or one can nest AND tests within OR tests, and so on.
One of the common errors in C is to confuse bit-wise logical OR with the OR test
discussed above. Theexpression if ((alpha < 5) | (beta == 0 ) ) gamma = 0; |
|||
encodes as |
|
|
|
|
LDAA |
alpha |
; get variable alpha |
|
CMPA |
#5 |
|
|
BLT |
LO |
; if greater or equal to 5 |
|
LDX |
#0 |
; generate zero |
|
BRA |
LI |
; and skip |
LO: |
LDX |
#1 |
; otherwise generate one |
LI: |
LDAA |
beta |
; test variable beta |
|
BEQ |
*+4 |
; if nonzero, branch to middle of CPS |
|
CLRB |
|
; otherwise clear B |
|
CPS |
#50689 ; address mode is actually LDAB #1 |
|
|
CLRA |
|
; high-order byte is always zero |
|
PSHX |
|
; OR X into D |
|
GRAB |
1, SP |
; by pushing X |
|
ORAA |
2,SP+ |
; then pulling it and ORing it into D |
|
TBEQ |
D, *+6 |
; if the result is nonzero |
|
CLR |
gamma |
; clear variable gamma |
What a difference a single character makes! Although the same answer is obtained with
the statement if ((alpha < 5) |
| j |
(beta = = 0 ) ) gamma = 0; as with if ((alpha |
||
< 5) | (beta == |
0 ) ) gamma = |
0;, the assembly language generated by the latter is |
||
significantly less efficient than that generated by the former statement. |
||||
Another of the common errors in C is to confuse assignment with equality test. The |
||||
expression if (beta |
== 0) |
gamma |
= 0; encodes as |
|
TST |
beta |
|
; test variable beta |
|
BNE |
*+5 |
|
; if the result is nonzero then |
|
CLR |
gamma |
|
; clear variable gamma |
|
The expression if (beta = |
0) |
gamma = 0; encodes as |
||
CLR |
beta |
|
; clear variable beta (note: this is an assignment statement) |
|
BNE |
*+5 |
|
; if the result is nonzero (it isn't) then |
|
CLR |
gamma |
; clear variable gamma |
||
From the rest of Figure 9.8, note how a string of else if ( . . . ) . . . else . . . ; statements cause the tests we have already discussed to be done, and when one is successful, so its following statement is executed, a branch is made to the end of the
series of else i f ( . . . |
) . . . else . . .; statements. Incidentally, the subroutine branched |
tobyBSR * +10 2 |
shifts the byte in beta left three places. |
