The 8051 Microcontroller Chapter 8 PROGRAM STRUCTURE AND

  • Slides: 49
Download presentation
The 8051 Microcontroller Chapter 8 PROGRAM STRUCTURE AND DESIGN

The 8051 Microcontroller Chapter 8 PROGRAM STRUCTURE AND DESIGN

 • In this chapter we introduce the characteristics of good programs and some

• In this chapter we introduce the characteristics of good programs and some techniques for developing good programs. • We begin with an introduction to structured programming techniques. • Structured programming is a technique for organizing and coding programs that reduces complexity, improves clarity, and facilitates debugging and modifying. 2

 • Progressing toward our goal-producing good assembly language programs-the example problems are solved

• Progressing toward our goal-producing good assembly language programs-the example problems are solved using three methods: – Flowcharts – Pseudo code – Assembly language • Flowcharts and pseudo code are useful tools for the initial stages. • Both of these are "visual" tools, facilitating the formulation and understanding of the problem. 3

4

4

 • Pseudo code is just what the name suggests: "sort of a computer

• Pseudo code is just what the name suggests: "sort of a computer language. • The idea has been used informally in the past as a convenient way to sketch out solutions to programming problems. • As applied here, pseudo code mimics the syntax of Pascal or C in its notation of structure, yet at the same time it encourages the use of natural language in describing actions. [get a character from the keyboard] 5

 • The benefit in using pseudo code lies in the strict adherence to

• The benefit in using pseudo code lies in the strict adherence to structure in combination with informal language. IF [condition is true] THEN [do statement 1] ELSE BEGIN [do statement 2] [do statement 3] END • or IF (the temperature is less than 20 degrees Celsius] THEN [wear a jacket] ELSE BEGIN [wear a short sleeve shirt] [bring sunglasses] END 6

ADVANTAGES AND DISADVANTAGES OF STRUCTURED PROGRAMMING • The advantages of adopting a structured approach

ADVANTAGES AND DISADVANTAGES OF STRUCTURED PROGRAMMING • The advantages of adopting a structured approach to programming are numerous. • These include the following: • The sequence of operations is simple to trace, thus facilitating debugging. • There a finite number of structures with standardized terminology. • Structures lend themselves easily to building subroutines. • The set of structures is complete; that is, a]1 programs can be written using three structures. • Structures are self-documenting and, therefore, easy to read. • Structures are easy to describe in flowcharts, syntax diagrams, pseudo code, and so on. • Structured programming results in increased programmer productivity-programs can be written faster. 7

 • However, some tradeoffs occur. • Structured programming has disadvantages, such as the

• However, some tradeoffs occur. • Structured programming has disadvantages, such as the following: • Only a few high-level languages (Pascal, C, PL/M) accept the structures directly; others require an extra stage of translation. • Structured programs may execute slower and require more memory than the unstructured equivalent. • Some problems (a minority) are more difficult to solve using only the three structures rather than a brute-force "spaghetti" approach. • Nested structures can be difficult to follow. 8

THE THREE STRUCTURES • All programming problems can be solved using three structures: –

THE THREE STRUCTURES • All programming problems can be solved using three structures: – Statements – Loops – Choice • The completeness of the three structures seems unlikely; but, with the addition of nesting (structures within structures), it is easily demonstrated that any programming problem can be solved using only three structures. 9

Statements • Statements provide the basic mechanism to do something. • Possibilities include: [count

Statements • Statements provide the basic mechanism to do something. • Possibilities include: [count = 0] PRINT_STRING("Select Option: ") • Anywhere a single statement can be used, a group of statements, or a statement block, can be used. BEGIN [statement 1] [statement 2] [statement 3] END 10

The Loop Structure • Used to repeatedly perform an operation. • Adding a series

The Loop Structure • Used to repeatedly perform an operation. • Adding a series of numbers or searching a list for a value are two examples of programming problems that require loops. • The term "iteration" is also used in this context. • Although there are several possible forms of loops, only two are necessary, WHILE/DO and REPEAT/UNTIL. 11

The WHILE/DO Statement • The WHILE/DO statement provides the easiest means for implementing loops.

The WHILE/DO Statement • The WHILE/DO statement provides the easiest means for implementing loops. • It is called a "statement, " since it is treated like a statement. WHILE [condition] DO [statement] 12

13

13

14

14

15

15

16

16

17

17

The REPEAT/UNTIL Statement • Similar to the WHILE/DO statement is the REPEAT/UNTIL statement, which

The REPEAT/UNTIL Statement • Similar to the WHILE/DO statement is the REPEAT/UNTIL statement, which is useful when the "repeat statement" must be performed at least once. 18

19

19

The Choice Structure • The third basic structure is that of "choice"the programmer's "fork

The Choice Structure • The third basic structure is that of "choice"the programmer's "fork in the road. “ • The two most common arrangements are the IF/THEN/ELSE statement and the CASE statement. 20

The IF/THEN/ELSE Statement • The IF/THEN/ELSE statement is used when one of two statements

The IF/THEN/ELSE Statement • The IF/THEN/ELSE statement is used when one of two statements (or statement blocks) must be chosen, depending on a condition. • The ELSE part of the statement is optional. 21

22

22

23

23

24

24

The CASE Statement • Handy variation of the IF/THEN/ELSE statement. • It is used

The CASE Statement • Handy variation of the IF/THEN/ELSE statement. • It is used when one statement from many must be chosen as determined by a value. 25

26

26

27

27

The GOTO Statement • GOTO statements can always be avoided by using the structures

The GOTO Statement • GOTO statements can always be avoided by using the structures presented. • Sometimes a GOTO statement provides an easy method of terminating a structure when errors occur. • In assembly language, GOTO statements usually become unconditional jump instructions. • A problem will arise, for example, if a subroutine is entered in the usual way (a CALL subroutine instruction), but is exited using a jump instruction rather than a return from subroutine instruction. • The return address will be left on the stack, and eventually a stack overflow will occur. 28

PSEUDO CODE SYNTAX • Since pseudo code is similar to a high-level language such

PSEUDO CODE SYNTAX • Since pseudo code is similar to a high-level language such as Pascal or C, it is worthwhile defining it somewhat more formally, so that, for example, a pseudo code program can be written by one programmer and converted to assembly language by another programmer. • While it offers the advantage of easy construction on a word processor (with subsequent modifications), it suffers from a disadvantage common to other programming languages: pseudo code programs are written line-by-line, so parallel operations are not immediately obvious. • With flowcharts, on the other hand, parallel operations can be placed physically adjacent to one another, thus improving the conceptual model. 29

 • The following tips are offered to enhance the power of solving programming

• The following tips are offered to enhance the power of solving programming problems, using pseudo code. • Use descriptive language for statements. • Avoid machine dependencies in statements. • Enclose conditions and statements in brackets: []. • Begin all subroutines with their names followed by a set of parentheses: (). Parameters passed to subroutines are entered (by name or by value) within the parentheses. • End all subroutines with RETURN followed by parentheses. Return values are entered within the parentheses. • Examples of subroutines: INCHAR() [statement] … RETURN(char) OUTCHR(char) [statement] STRLEN(pointer) [statement] … … RETURN() RETURN(length) 30

 • Use lowercase text except for reserved words and subroutine names. • Indent

• Use lowercase text except for reserved words and subroutine names. • Indent all statements from the structure entry and exit points. When a LOOP or CHOOSE structure is started, the statements within the structure appear at the next level of indentation. • Use the commercial at sign (@) for indirect addressing. 31

 • The following is a suggested syntax for pseudo code. • Reserved Words:

• The following is a suggested syntax for pseudo code. • Reserved Words: BEGIN END REPEAT UNTIL WHILE DO IF THEN ELSE CASE OF RETURN • Arithmetic Operators: + addition subtraction * multiplication / division % modulus (remainder after division) 32

 • Related Operators: (result is true or false) == true if values equal

• Related Operators: (result is true or false) == true if values equal to each other != true if values not equal < true if first value less than second <= true if first value <= second value > true if first value > second value >= true if first value >= second value && true if both values are true || true if either value is true • Bitwise Logical Operators: & logical AND | logical OR ^ logical exclusive OR ~ logical NOT (one's complement) >> logical shift right << logical shift left 33

 • Assignment Operators: = set equal to op = assignment operation shorthand where

• Assignment Operators: = set equal to op = assignment operation shorthand where "op" is one of + - * / % << >> & ^ | e. g. : j += 4 is equivalent to j = j + 4 • Precedence Operation: () • Indirect Address: @ 34

 • Note 1. Do not confuse relational operators with bitwise logical operators. Bitwise

• Note 1. Do not confuse relational operators with bitwise logical operators. Bitwise logical operators are generally used in assignment statements such as [lower nibble = byte & OFH] • whereas relational operators are generally used in conditional expressions such as IF (char != 'Q' && char != ODH) THEN. . . • Note 2. Do not confuse the relational operator "==" with the assignment operator "=" For example, the Boolean expression j == 9 • is either true or false depending on whether or not j is equal to the value 9, whereas the assignment statement j=9 • assigns the value 9 to the variable j. 36

 • Structures: • Statement: [do something] • Statement Block: BEGIN [statement] … END

• Structures: • Statement: [do something] • Statement Block: BEGIN [statement] … END • WHILE/DO: WHILE [condition] DO [statement] • REPEAT/UNTIL: REPEAT [statement] UNTIL [condition] 37

 • IF/THEN/ELSE: IF [condition] THEN [statement 1] (ELSE [statement 2]) • CASE/OF: CASE

• IF/THEN/ELSE: IF [condition] THEN [statement 1] (ELSE [statement 2]) • CASE/OF: CASE [expression] OF 1: [statement 1] 2: [statement 2] 3: [statement 3] … n: [statement n] [default statement] END 38

ASSEMBLY LANGUAGE PROGRAMMING STYLE • It is important to adopt a clear and consistent

ASSEMBLY LANGUAGE PROGRAMMING STYLE • It is important to adopt a clear and consistent style in assembly language programming. • This is particularly important when one is working as part of a team, since individuals must be able to read and understand each other's programs. • The assembly language solutions to problems up to this point have been deliberately sketchy. • For larger programming tasks, however, a more critical approach is required. • The following tips are offered to help improve assembly language programming style. 39

Labels • Use labels that are descriptive of the destination they represent. • For

Labels • Use labels that are descriptive of the destination they represent. • For example, when branching back to repeatedly perform an operation, use a label such as "LOOP, " "BACK, " "MORE, " etc. • When skipping over a few instructions in the program, use a label such as "SKIP" or "AHEAD. " • When repeatedly checking a status bit, use a label such as "WAIT" or "AGAIN. " • The choice of labels is restricted somewhat when one is using a simple memory-resident or absolute assembler. These assemblers treat the entire program as a unit, thus limiting the use of common labels. Several techniques circumvent this problem. • Common labels can be sequentially numbered, such as SKIP 1, SKIP 2, SKIP 3, etc. ; or perhaps within subroutines all labels can use the name of the subroutine followed by a number, such as SEND, SEND 2, SEND 3, etc. • There is an obvious loss of clarity here. • More sophisticated assemblers, such as ASM 51, allow each subroutine (or a common group of subroutines) to exist as a separate file that is assembled independent of the main program. This type of assembler, usually called a "relocatable" assembler, allows the same label to appear in different files. 40

Comments • The use of comments cannot be overemphasized, particularly in assembly language programming,

Comments • The use of comments cannot be overemphasized, particularly in assembly language programming, which is inherently abstract. • All lines of code, except those with truly obvious actions, should include a comment. • Conditional jump instructions are effectively commented using a question similar to the flowchart question for a similar operation. • The "yes" and "no" answers to the question should appear in comments at the lines representing the `jump" and "no jump" actions. 41

Comment Blocks • Comment lines are essential at the beginning of each subroutine. •

Comment Blocks • Comment lines are essential at the beginning of each subroutine. • Since subroutines perform well-defined tasks commonly needed throughout a program, they should be generalpurpose and well documented. • Each subroutine is preceded by a comment block, a series of comment lines that explicitly state: • The name of the subroutine • The operation performed • Entry conditions • Exit conditions • Name of other subroutines used (if any) • Name of registers affected by the subroutine (if any) 42

43

43

Saving Registers on the Stack • As applications grow in size and complexity, new

Saving Registers on the Stack • As applications grow in size and complexity, new subroutines are often written that build upon and use existing subroutines. Thus, subroutines are calling other subroutines, which in turn call other subroutines, and so on. These are called "nested subroutines. " There is no danger in nesting subroutines so long as the stack has enough room to hold the return addresses. This is not a problem, since nesting beyond several levels is rare. • A potential problem, however, lies in the use of registers within subroutines. • A solid programming practice is to save registers on the stack that are altered by a subroutine, and then restore them at the end of the subroutine. 44

The Use of Equates • Defining constants with equate statements makes programs easier to

The Use of Equates • Defining constants with equate statements makes programs easier to read and maintain. • Equates appear at the beginning of a program to define constants such as carriage return (<CR>) and line feed (<LF>), or addresses of registers inside peripheral ICs such as STATUS or CONTROL. • A generous use of equates makes a program more maintainable, as well as more readable. • If a constant must be changed, only one line needs changing-the line where the symbol is equated. 45

The Use of Subroutines • As programs grow in size, it is important to

The Use of Subroutines • As programs grow in size, it is important to "divide and conquer"; that is, subdivide large and complex operations into small and simple operations. These small and simple operations are programmed as subroutines. Subroutines are hierarchical in that simple subroutines can be used by more complex subroutines, and so on. • A flowchart references a subroutine using the "predefined process" box. The use of this symbol indicates that another flowchart elsewhere describes the details of the operation. • Subroutines are constructed in pseudo code as complete sections of code, beginning with their names and parentheses. Within the parentheses are the names or values of parameters passed to the subroutine (if any). Each subroutine ends with the keyword RETURN followed by parentheses containing the name or value of parameters returned by the subroutine (if any). 46

47

47

48

48

Program Organization • Although programs are often written piecemeal (i. e. , subroutines are

Program Organization • Although programs are often written piecemeal (i. e. , subroutines are written separately from the main program), all programs should be consistent in their final organization. In general, the sections of a program are ordered as follows: • Equates • Initialization instructions • Main body of program • Subroutines • Data constant definitions (DB and DW) • RAM data locations defined using the DS directive • All but the last item above are called the "code segment, " and the RAM data locations are called the "data segment. " • Code and data segments are traditionally separate, since code is often destined for ROM or EPROM, whereas RAM data are always destined for RAM. • Note that data constants and strings defined using the DB or DW directives are part of the code segment (not the data segment), since these data are unchanging constants and, therefore, are part of the program. 49