ece 4510/5530 microcontroller applications chapter...
TRANSCRIPT
ECE 4510/5530Microcontroller Applications
Chapter 4
Dr. Bradley J. BazuinAssociate Professor
Department of Electrical and Computer EngineeringCollege of Engineering and Applied Sciences
ECE 2510 2
Chapter 4
• Advanced Assembly Programming– Program = data structures + algorithm
• Data structures to be discussed– Stacks: a first-in-last-out data structure– Arrays: a set of elements of the same type– Strings: a sequence of characters terminated by a special character– Stack Frames
• Examples– Finding a value in an unsorted array– Finding a value in a sorted array– Binary to BCD to ASCII outputs and inputs– ASCII word matching, insertion– Subroutines
ECE 2510
top element
bottom element
low address
high address
Stack pointer
Figure 4.1 Diagram of the HCS12 stack
Stacks
• Stack– Start at the top of usable RAM space ($3C00 – 1 is highest address)– To store: Pre-decrement the stack pointer and write data– To load: read data and post-increment the stack pointer
ECE 2510 4
Simple Stack Operations
• A simple means to store and retrieve register values temporarily– Notice that words inc/dec stack by 2
• The SP can also be used in most instances where X and Y are used– Auto-inc/dec addressing modes
Stack Operation Instructions Mnemonic Function Operation
PSHA Push A (SP) – 1 SP; (A) M(SP)
PSHB Push B (SP) – 1 SP; (B) M(SP)
PSHC Push CCR (SP) – 1 SP; (A) M(SP)
PSHD Push D (SP) – 2 SP; (A : B) M(SP) : M(SP+1)
PSHX Push X (SP) – 2 SP; (X) M(SP) : M(SP+1)
PSHY Push Y (SP) – 2 SP; (Y) M(SP) : M(SP+1)
PULA Pull A (M(SP)) A; (SP) + 1 SP
PULB Pull B (M(SP)) B; (SP) + 1 SP
PULC Pull CCR (M(SP)) CCR; (SP) + 1 SP
PULD Pull D (M(SP) : M(SP+1)) A : B; (SP) + 2 SP
PULX Pull X (M(SP) : M(SP+1)) X; (SP) + 2 SP
PULY Pull Y (M(SP) : M(SP+1)) Y; (SP) + 2 SP
ECE 2510 5
HC12 Memory Allocation
• RAM area for HCS12 $0800 - $3FFF
• Data Memory $0800 - $11FF• Program Memory $122A - $3BFF • Stack Pointer $3C00• D-Bug12 RAM $3C00-$3FFF
Freescale Semiconductor, Inc., 9S12DP512DGV1/D Device Guide V01.25, Original Release Date: 27 Nov , Revised: July 5, 2005.
ECE 2510 6
Sorting Odds and Evens
• Using a stack #1– Push the entire data array onto the stack backwards– Pull/Pop one piece of data at a time and put it where it belongs
• Positive/negative, odd/even, etc.
• Using a stack #2– Push the entire data array onto the stack– Pull/Pop one piece of data at a time and put on one of two other
stacks• X and Y can be used as stack pointers!• Auto-inc/dec addressing modes
ECE 2510 7
Indexed Data Structures
• Vectors and matrices are indexed data structures.• The first element of a vector is associated with the index 0
in order to facilitate the address calculation.• Assemblers directives .byte or .blkb are used to define
arrays of 8-bit elements.• Assemblers directives .word or .blkw are used to define
arrays of 16-bit elements.
ECE 2510 8
Example 4.2
• Example 4.2 – Write a program to find out if the array vec_x contains a value ‘key’. – The array has 16-bit elements and is not sorted.
• Since the array is not sorted, we need to compare the key with every array element until it is found.
• Searching an array is a common operation for microcontroller applications– If the arrays is not sorted, the only way to find out whether a value is in
the array is by performing the sequential search– Sequential search algorithm compares the value to be searched with every
element in the array• If an array needs to be searched frequently then sequential search is
very in-efficient– A better approach is to sort the array and perform a binary search
algorithm
ECE 2510 9
One Solution:– Use the double
accumulator D to hold the key.
– Use the index register X as a pointer to the array.
– Use the index register Y to hold the loop count.
Example 4.2 Flowchart
Start
i = 0result = -1
vec_x[i] = key?
i = N - 1?
i = i + 1 result = address of vec_x[i]
Stop
Figure 4.3 Flowchart for sequential search
yes
yes
no
no
ECE 2510 10
Example 4.2 Code
N = 30 ; array countnotfound = -1key = 190 ; define the searching key.org $1000vec_x: .word 13,15,320,980,42,86,130,319,430,4, 90,20,18,55,30,51,37
.word 89,550,39, 78,1023,897,930,880,810,650,710,300,190.org $1100result: .blkw 1 ; reserve a word for result.text_main:: ; starting point of the program
ldy #N ; set up loop countldd #notfoundstd result ; initialize the search resultldd #keyldx #vec_x ; place the starting address of vec_x in X
loop: cpd 2,X+ ; compare the key with array element & move pointerbeq founddbne Y,loop ; have we gone through the whole array?bra done
found: dex ; need to restore the value of X to point to thedex ; matched elementstx result
done: swi
ECE 2510 11
Searching a Sorted Array
• If an array needs to be searched frequently then sort the array first and perform a different search algorithm.
• Binary Search– First: Is the key between the 1st and last array index values?
• No – your done and have no match– Two: Check to see if max<min
• If true – you are done and have no match– Third: Compare the key to the middle index (max-min)/2
• Equal to – you are done and have a match• Greater than – set max to current index -1 and goto step 2 • Less than – set min to current index +1 and goto step 2
ECE 2510 12
Example 4.3: Binary Search
• Write a program to implement the binary search algorithm and also a sequence of instructions to test it.– Array sorted in ascending order.– 8-bit characters
• Variables used for a binary search– Max and min represent the highest and lowest range of the array
index– Mean represent the average of max and min
• Binary search algorithms divide the sorted array into three parts– Portion of the array with indices ranging from mean+1 to max– Element with index equal to mean– Portion of the array with indices ranging from min to mean-1
ECE 2510 13
Code (1)n = 30 ; array countkey = 69 ; key to be searched.org $1000arr: .byte 1,3,6,9,11,20,30,45,48,60
.byte 61,63,64,65,67,69,72,74,76,79
.byte 80,83,85,88,90,110,113,114,120,123arrend:
.org $1100max .blkb 1 ; maximum index value for comparisonmin .blkb 1 ; minimum index value for comparisonmean .blkb 1 ; the average of max and minresult .blkb 1 ; search result
.text_main::
clrastaa min ; initialize min to 0staa result ; initialize result to 0ldaa #n-1staa max ; initialize max to n-1ldx #arr ; use X as the pointer to the array
ECE 2510 14
Code (2)loop: ldab min
cmpb maxlbhi notfound ; branch if min>maxaddb max ; compute mean, unsigned addlsrb ; divide by twostab mean ; save meanldaa b,x ; get a copy of the element arr[mean]cmpa #keybeq found ; if equal - foundbhi search_lo ; if arr[mean] >key – in
search_hi: ldaa meanincastaa min ; place mean+1 in min to continuebra loop
search_lo: ldaa meandecastaa maxbra loop
found: ldaa #1staa result
notfound: swi
ECE 2510 15
ASCII Strings
• A sequence of ASCII characters terminated by a NULL (ASCII code 0) or other special character such as EOT (ASCII code 4).
• Many Output devices recognizes ASCII characters– Devices like CRT monitors and LCD (Liquid Crystal Displays)
• For text editing, we must be able to:– Form ASCII arrays, move ASCII arrays, combine ASCII arrays,
append to ASCII arrays, etc. – Search ASCII arrays, replace strings with strings, etc.
• Numbers first, then Text …
ECE 2510 16
Binary to BCD ASCII Strings
• Numerical input and output is typically performed as an ASCII BCD representation– A number in the computer is represented as a binary number.– A number must be converted to ASCII code before output so that it
can be understood.– The ASCII equivalent for decimal 0 – 9 is 30 – 39.
• To convert a binary into an ASCII string, we divide the binary number by 10 repeatedly until the quotient is zero. For each remainder, the number $30 is added.
ECE 2510 17
Example 4.4: ASCII BCD Output
• Write a program to convert the unsigned 8-bit binary number in accumulator A into ASCII BCD digits terminated by a NULL character. Each digit is represented in ASCII code.
• There are from 2 to 4 bytes needed for the result (max >=100 plus NULL , min 0 plus NULL )
• Work from LSdigit to MSdigit– Push results on the stack so they can be “output” in the proper
order, MS_BCD first
ECE 2510 18
Example 4.4: Code (1)
test_dat = 34.org $1000
.org $1100buf: . blkb 4 ; to hold the decimal string, initialize to nulltemp: .blkb 2 ; "
.text_main::
ldab #test_datlds #$3C00 ; initialize stack pointerldy #buftstbbne normal ; if the value is not zero, start the loopmovb #0,1,-sp ; push a NULL into the stack (mod from text)movb #$30,1,-sp ; store ASCII BCD 0 into the stack (mod)bra reverse ; store to buf (mod)
ECE 2510 19
Example 4.4: Code (2)normal: movb #0,1,-sp ; push a NULL into the stack
clraloop: ldx #10
idivaddb #$30 ; convert to ASCII codepshb ; push into stackcpx #0beq reverse ; if result of division is zero, reversexgdx ; put quotient back to Bbra loop
reverse: movb 0,sp,1,y+tst 0,spbeq done ; when the null is found, doneinsbra reverse
done: insswi
ECE 2510 20
Signed binary numbers to ASCII strings Conversion
• Step1:– Check if the number is negative using bmi instruction – If negative first step is to add $2D (ASCII equivalent of -) to the
start of the ASCII string
• Step2:– Compute the 2’s complement of the number
• Step3:– Divide the binary number by 10 ($0A) repeatedly until the quotient
is zero– For each remainder the number $30 needs to be added to convert
the number into a recognizable ASCII string
ECE 2510 21
Numerical Example
Ex: F652• Step1: Since negative number add $2D to the start of ASCII string• Step2: 2’s Complement of F652 = $09AE• Step3: $9AE/$A Quotient = $F7, Remainder = $8, ASCII = $38• Step4: $F7/$A Quotient = $18, Remainder = $7, ASCII = $37• Step5: $18/$A Quotient = $2, Remainder = $4, ASCII = $34• Step6: $2/$A Quotient = 0, Remainder = $2, ASCII = $32
ASCII String generated = “$2D,$32,$34,$37,$38”ASCII string provided as test_data: .ascii "-2478“ yields an outputlisting of 2D32343738 test_data: .ascii "-2478"
ECE 2510 22
Example 4.5: ASCII BCD Output
• Write a program to convert a signed 16-bit binary number in accumulator D into ASCII BCD digits terminated by a NULL character. Each digit is represented in ASCII code.
• Solution Elements– A signed 16-bit integer is in the range of -32768 to +32767.– A NULL character is needed to terminate the converted BCD
string.– A minus character is needed for a negative number.– If negative, check if -32768 and finish or write ASCII(-) and take a
two’s complement to form an “unsigned” integer– Up to 7 bytes are needed to hold the converted result.
ECE 2510 23
Example 4.5: Code (1)test_dat = -2478.org $1000buf: .blkb 7 ; to hold the decimal string
.text_main::
ldd #test_datlds #$3C00 ; initialize stack pointerldy #bufcpd #0bmi negate ; branch if the value is negativebne normal ; branch if the value is positivemovb #$30,bufclr buf+1 ; terminate the stringbra done
negate: coma ; when negative, complement the numbercomb ; "addd #1 ; and add 1movb #$2D,1,y+ ; add minus sign and move y pointer
ECE 2510 24
Example 4.5: Code (2)
normal: movb #0,1,-sp ; push a NULL into the stack
loop: ldx #10
idiv ; (D) ÷ (X) X, Remainder Daddb #$30 ; convert to ASCII codepshb ; push into stackcpx #0 ; is the quotient zero?beq reversexgdx ; put quotient back to D, (D) (X) bra loop
reverse: tst 0,sp ; Is the value a null? If so, done.beq done ; Note: null not written to buffer this way!!movb 1,sp+,1,y+ ; pop one byte and store it in bufferbra reverse
done: swi
ECE 2510 25
ASCII string to Binary conversion
• Input provided by most of the devices is often in the form of the NULL terminated ASCII string– ASCII string needs to be converted to the binary mode before the
controller can process the data– Input devices like keypads, keyboards etc provide input in the
ASCII strings
• Data provided by the input devices can be both positive or negative numbers– So algorithm developed should check for the – ASCII characters
since negative numbers will be accompanied by the – ($2D) ASCII character
ECE 2510 26
ASCII strings to Signed binary number Conversion
• Step1:– Check for the negative number. If negative then the finally computed
binary number should be converted to its 2’s complement form• Step2:
– Make sure that the character is a valid BCD digit i.e. >=$30 and <=$39– If valid BCD number then continue
• Step3:– Number = number * 10 + ASCII_Value-$30
(Number initialized to 0 in the beginning)– In the string the value to the left is the first digit to be implemented in the
above equation• Step4:
– If negative, take the two’s complement of he binary result
ECE 2510 27
Numerical Example
Ex: Data provided by the Input device is “2D32343738” (-2478 BCD)• Step1: Since first byte is $2D, indicates the value is a negative number• Step2: initialize number = 0 number = 0*A+$32-$30= 2• Step3: number = 2*A + $34 – $30 = $18• Step4: number = $18*A + $37 - $30 = $F7• Step5: number = $F7 * A + $38 - $30 = $9AEBinary representation = 0000 1001 1010 1110Need to compute 2’S complement since it’s a negative number
1111 0110 0101 0001+ 1-------------------------------
1111 0110 0101 0010 F652
ECE 2510 28
Example 4.6: ASCII BCD Input
• Write a program to convert a BCD ASCII string to a binary number• Pseudo Code
Step 1sign 0error 0number 0
Step 2If the character pointed to by in_ptr is the minus sign, then
sign 1in_ptr in_ptr + 1
Step 3If the character pointed to by in_ptr is the NULL character,
then go to step 4.else if the character is not a BCD digit,
then error 1; go to step 4;else
number number * 10 + m[in_ptr] - $30;in_ptr in_ptr + 1;go to step 3;
Step 4If sign = 1 and error = 0 ,then
number two’s complement of number;else
stop;
Is there something missing?
ECE 2510 29
Example 4.6: Code (1)minus = $2D ; ASCII code of minus sign.org $1000in_buf: .ascii 9889 ; input ASCII to be converted
.byte 0 ; null character.org $1100out_buf: .blkb 2 ; holds the converted binary valuebuf2: .blkb 1 ; holds a zerobuf1: .blkb 1 ; holds the current digit value sign: .blkb 1 ; holds the sign of the number error: .blkb 1 ; indicates the occurrence of illegal character.text_main:: clr sign
clr errorclr out_bufclr out_buf+1clr buf2ldx #in_bufldaa 0,xcmpa #minus ; is the first character a minus sign?bne continue ; branch if not minusinc sign ; set the sign to 1inx ; move the pointer
ECE 2510 30
Example 4.6: Code (2)continue: ldaa 1,x+ ; is the current character a NULL character?
lbeq done ; yes, we reach the end of the stringcmpa #$30 ; is the character not between 0 to 9?lblo in_error ; "cmpa #$39 ; "lbhi in_error ; "suba #$30 ; convert to the BCD digit valuestaa buf1 ; save the digit temporarilyldd out_bufldy #10emul ; perform 16-bit by 16-bit multiplicationaddd buf2 ; add the current digit valuestd out_buf ; Y holds 0 and should be ignoredbra continue
in_error: ldaa #1staa error
ECE 2510 31
Example 4.6: Code (3)
done: ldaa sign ; check to see if the original number is negativebeq positiveldaa out_buf ; if negative, compute its two’s complementldab out_buf+1 ; “coma ; “comb ; “addd #1 ; “std out_buf
positive: swi
ECE 2510 32
ASCII Assembler Directives for Text
.ascii "strings"
.asciz "strings"• .asciz adds a NUL character (\0) at the end.
• These directives are used to define strings, which must be enclosed in a delimiter pair. The delimiter can be any character as long as the beginning delimiter matches the closing delimiter. Within the delimiters, any printable ASCII characters are valid, plus the following C-style escape characters, all of which start with a backslash (\):
\e escape \b backspace \f form feed \n line feed \r carriage return \t tab \<up to 3 octal digits> character with value equal to the octal digits
Examples: .asciz "Hello World\n" .asciz "123\0456"
ECE 2510 33
Text Manipulations
• Word Counting• Character Counting• Line Parsing• Text Search• Text insertion and deletion• Detection of punctuation and non-printed characters
ECE 2510 34
Character and Word Counting
• Spaces, carriage return etc. in a string should be included in the character count– Needs to be included in the character count since they occupy disk
space when a string is saved.
• A new word is identified by skipping over the white space characters.– When a new word is identified, it must be scanned through before
the next word can be identified.
• Operations with strings involve– Character and word counting– Word matching– String insertion
ECE 2510 35
Example 4.7: Word/Character Count
• Count the number of characters and words– Count all ascii characters– Only count words– White space
(CR, LF, Tab, Space)
• Variables:– Character Count– Word Count– Current Character– Character Pointer
Start
char_cnt 0word_cnt 0str_ptr addr. of string
curr_char [str_ptr]
str_ptr str_ptr + 1
curr_char = space, CR, LF, or tab?
word_cnt word_cnt + 1
curr_char [str_ptr]
str_ptr str_ptr + 1
curr_char = NULL?
char_cnt char_cnt + 1
curr_char = NULL?
char_cnt char_cnt + 1
curr_char = space, CR, LF, or tab?
Stop
Stop
Skip white spaces
reach a new word
skip the remaining characters of the word
yes
yes
no
no
yes
no
no
yes
ECE 2510 36
Example 4.7: Code (1).area program(abs) ; command to indicate the absolute start of the programtab = $09sp = $20cr = $0Dlf = $0A.org $1000 ; command forces the controller to start the programstring_x: fcc "this is a strange test string to count chars and words."
.byte 0.org $1100char_cnt .blkb 1word_cnt .blkb 1
.text_main::
ldx #string_xclr char_cntclr word_cnt
ECE 2510 37
Example 4.7: Code (2)string_lp: ldab 1,x+ ; get one character and move string pointer
lbeq done ; is this the end of the string?inc char_cnt
; the following 8 instructions skip white space characters between wordscmpb #spbeq string_lpcmpb #tabbeq string_lpcmpb #crbeq string_lpcmpb #lfbeq string_lp
; a non-white character is the start of a new wordinc word_cnt
ECE 2510 38
Example 4.7: Code (3)
wd_loop: ldab 1,x+ ; get one character and move pointerbeq doneinc char_cnt
; the following 8 instructions check the end of a wordcmpb #splbeq string_lpcmpb #tablbeq string_lpcmpb #crlbeq string_lpcmpb #lflbeq string_lpbra wd_loop
Done: swiend
ECE 2510 39
Word Matching
• Searching for certain words from a string is a common operation– Searching process starts from the beginning of the given string– Comparison is performed character by character until either two
words are found to be matched or unmatched– If two words are not equal, then the remaining characters of the
word in the string must be skipped so that the same process can be repeated
• When searching strings or working with strings, the program needs to look for the NULL character, since it represents the end of a string.
ECE 2510 40
Word Matching Flow
• Search Routine– Full word option– Partial word option
– Skip white space– Test for full search
word – Special word end
considerations (punctuation, white space, null)
ECE 2510 41
Complete Flow DiagramStart
[str_ptr] = NULL?
str_ptr string_xmatch_flag 0
[str_ptr] = space, tab, CR, or lf?
wd_ptr word_x
[str_ptr] = [wd_ptr] ?
[wd_ptr] = NULL?
[str_ptr] = NULL?
[str_ptr] = space, tab, CR, or lf?
str_ptr str_ptr + 1
Stop
no
no
Stop
no
yes
str_ptr str_ptr + 1
yes
no
[str_ptr] = NULL?
match_flag 1
Stop
wd_ptr wd_ptr + 1str_ptr str_ptr + 1
str_ptr str_ptr + 1
yes
yes
yes
yes
no
no
no
[str_ptr] = space, tab, CR, lf, or punctuation
mark?
no
yes
yes (matched)
move to the next word to be compared
compare two words
skip the unmatched
word
ECE 2510 42
Example 4.8: Code (1).area program(abs) ; command to indicate the absolute start of the programtab: = $09 ; ASCII code of tab sp: = $20 ; ASCII code of space charactercr: = $0D ; ASCII code of carriage returnlf: = $0A ; ASCII code of line feedperiod: = $2E ; ASCII code of periodcomma: = $2C ; ASCII code of commasemicolon: = $3B ; ASCII code of semicolonexclamation: = $21 ; ASCII code of exclamationnull: = $0 ; ASCII code of NULL character
.org $1000string_x: .asciiz "This string contains certain number of words to be matched."
.byte 0word_x: .asciiz "This"
.byte 0
.org $1100match: .blkb 1
ECE 2510 43
Example 4.8: Code (2).text_main::
clr matchldx #string_x
loop: ldab 1,x+; the following 10 instructions skip white spaces to look for the next word in string_x
tstbbeq donecmpb #spbeq loopcmpb #tabbeq loopcmpb #crbeq loopcmpb #lfbeq loop
ECE 2510 44
Example 4.8: Code (3); the first nonwhite character is the beginning of a new word to be compared
ldy #word_xldaa 1,y+
next_ch: cbabne EndOfWdcmpa #null ; check to see if the end of word is reachedbeq matched ; "ldaa 1,y+ ; get the next character from the wordldab 1,x+ ; get the next character from the stringbra next_ch
ECE 2510 45
Example 4.8: Code (4); the following 10 instructions check to see if the end of the given word is reachedEndOfWd: cmpa #null ; if a is a null check b for NPC
bne next_wd ; if a is not it is not a matchcmpb #cr ; NPC character testingbeq matchedcmpb #lfbeq matchedcmpb #tabbeq matchedcmpb #spbeq matchedcmpb #periodbeq matchedcmpb #commabeq matchedcmpb #semicolonbeq matchedcmpb #exclamationbeq matched
ECE 2510 46
Example 4.8: Code (5); the following 11 instructions skip the remaining characters in the unmatched wordnext_wd: ldab 1,x+ ; load the next char into B
beq done ; if a null, the string is donecmpb #cr ; loop if CR, LF, TAB, SP lbeq loopcmpb #lflbeq loopcmpb #tablbeq loopcmpb #splbeq loopbra next_wd ; else keep moving through “wrong” word
matched: ldab #1 ; word match foundstab match ; store word match indicator
done: swi
ECE 2510 47
String Insertion
• Inserting a substring into a string is another common operation– The insertion point will be given for such an operation– To insert a substring into a string, one needs to make room for the
substring to be inserted– All the characters starting from the inserting point until the end of
the string must be moved by the distance equal to the length of the substring
ECE 2510 48
String Insertion
ECE 2510 49
String Insertion
• Step1: – Count the number of characters that need to be moved. Null
character is also included since the new string must be terminated by a null character
• Step2: – Count the number of characters in the substring to be inserted
• Step3: – Move the characters in the string starting from the insertion point
until the end of the string
• Step4: – Insert the substring
ECE 2510 50
Example 4.9: Code (1).area program(abs) ; command to indicate the absolute start of the program
offset = 15ins_pos = string_x+offset ; insertion point
.org $1000sub_strg: .ascii "the first and most famous "
.byte 0.org $1080string_x: .ascii "Yellowstone is national park."
.byte 0.org $1100ch_moved:.blkb 1 ; number of characters to be movedchar_cnt: .blkb 1 ; number of characters of the substring to be inserted
ECE 2510 51
Example 4.9: Code (2).text_main::
; the first 7 instructions count the number of characters to be movedldaa #1staa ch_movedldx #ins_pos ; x points to the insertion point
cnt_moved: ldaa 1,x+beq cnt_charsinc ch_movedbra cnt_moved
cnt_chars: dex ; subtract 1 from x so it points to the NULL characterldy #sub_strg ; y points to the substring clr char_cnt
ECE 2510 52
Example 4.9: Code (3); the following 4 instructions count the move distancechar_loop: ldab 1,y+
beq mov_loopinc char_cntbra char_loop
mov_loop: tfr x,y ; make a copy of x in yldab char_cntaby ; compute the copy destinationldab ch_moved ; place the number of characters to be moved in B
again: movb 1,x-,1,y-dbne b,again ; make room for insertion
ldx #ins_pos ; set up pointers to prepare insertionldy #sub_strg ; "ldab char_cnt
insert_lp: movb 1,y+,1,x+dbne b,insert_lpswi
ECE 2510 53
HC12 Memory Allocation
• RAM area for HCS12 $1000 - $3FFF
• Data Memory $1000 - $1229• Program Memory $122A - $3BFF • Stack Pointer $3C00• D-Bug12 RAM $3C00-$3FFF
Freescale Semiconductor, Inc., MC9S12DP256B Device User Guide V02.15, Original Release Date: 29 Mar 2001, Revised: Jan 11, 2005.
ECE 2510 54
Subroutines
• Good program design is based on the concept of modularity– Modularity partitioning of a large program into subroutines
• Program can be divided into two sections– Main program– Subroutines
• Main program contains the logical structure of the algorithm
• Subroutines Execute many of the details involved in the program
ECE 2510 55
Subroutine Hierarchy
• Structure of a modular program can be visualized as shown• Principles of program design involved in high-level
languages can be applied to assembly language programs– Subroutine “objects” with calls and returns
ECE 2510 56
Subroutines
• Subroutine is a sequence of instructions that can be called from many different places in a program– One key issue in a subroutine call is to make sure that the program
execution returns to the point immediately after the subroutine call when the subroutine completes its computation
• The address for returning to the point immediately after the subroutine completes its computation is known as the return address– This is normally achieved by saving and retrieving the return
address in and from the stack
ECE 2510 57
Subroutine Program Flow
• The subroutine call saves the return address, which is the address of the instruction immediately following the subroutine call instruction, in the stack system
• After completing the computation task, the subroutine will return to the instruction immediately following the instruction that makes the subroutine call
• This is achieved by executing a return instruction, which will retrieve the return address from the stack and transfer CPU control to it
ECE 2510
Issues in Subroutine Calls
• Parameter passing – Use registers– Use the stack or stack frame– Use global memory
• Returning results– Use registers– Use the stack frame
(caller created a hole in which the result will be placed)
– Use global memory
• Local variables allocation– Allocated by the callee– Use the following instruction is
the most efficient way for local variable allocation
– leas -n,sp ; • allocate n bytes in the stack
for local variables
• Local variables deallocation– Performed by the subroutine– Use the following instruction is
the most efficient way– Leas n,sp ;
• deallocate n bytes from the stack
ECE 2510 59
HCS12 Subroutines Instructions
• HCS12 provides three different instructions for making subroutine calls and two different instructions for returning from a subroutine
• Subroutine calls– BSR Branch Subroutine– JSR Jump Subroutine– Call Call a Subroutine
• Return Instructions– RTS Return from Subroutine– RTC Return from Call
ECE 2510 60
Jump and Subroutine TableMnemonic Function Operation
BSR Branch to subroutine SP – 2 SP RTNH : RTNL M(SP) : M(SP+1)Subroutine address PC
CALL Call subroutine in expanded memory SP – 2 SPRTNH:RTNL M(SP) : M(SP+1)SP – 1 SP(PPAGE) M(SP)Page PPAGESubroutine address PC
JMP Jump Address PC
JSR Jump to subroutine SP – 2 SPRTNH : RTNL M(SP) : M(SP+1)Subroutine address PC
RTC Return from call M(SP) PPAGESP + 1 SPM(SP) : M(SP+1) PCH : PCLSP + 2 SP
RTS Return from subroutine M(SP) : M(SP+1) PCH : PCLSP + 2 SP
ECE 2510 61
Branch to Subroutine
BSR <REL>• This instruction allows to use only relative addressing mode to specify
the subroutine to be called– When this instruction is executed, the stack pointer is decremented by two
and the return address is saved in the stack– The offset in the instruction is added to the current PC value and
instruction execution is continued from there• In assembly language, the relative address is specified by using a label
– The assembler will calculate the relative offset and places it in the program memory
Ex: bsr bubble
ECE 2510 62
Jump to Subroutine
JSR <OPR>• This instruction is allowed to use direct, extended, indexed and
indexed indirect addressing mode to specify the subroutine to be called– The subroutine can be located anywhere with the 64kB memory map– This instruction also saves the return address in the stack and then jumps
to execute the subroutineEx:
Jsr $FFJsr sq_rootJsr 0,x
ECE 2510 63
Return from Subroutine
RTS• This instruction loads the program counter with a 16-bit
value pulled from the stack and increments the stack pointer by 2
• Program execution continues at the address restored from the stack
• Used with BSR and JSR
PC_HighByte:PC_LowByte PC
SP $3C00
SP
$3C00
$3BFF
$3BFE
PC_LowByte
PC_HighByte
ECE 2510 64
Call and Return from Call
CALL <OPR>• This instruction is designed to work with expanded
memory larger than 64KB supported by some HCS12 members
RTC• This instruction terminates subroutines in expanded
memory invoked by the call instruction
ECE 2510 65
Equivalent Push/Pull instructions
• PUSH InstructionsPsha Push A into the stack staa 1,-SPPshb Push B into the stack stab 1,-SPPshd Push D into the stack std 2,-SPPshx Push X into the stack stx 2,-SPPshy Push Y into the stack sty 2,-SP
• Pull InstructionsPula Pull A from the stack ldaa 1,SP+Pulb Pull B from the stack ldab 1,SP+Puld Pull D from the stack ldd 2,SP+Pulx Pull X from the stack ldx 2,SP+Puly Pull Y from the stack ldy 2,SP+
ECE 2510 66
Additional Stack Instructions
LEAS Load stack pointer with effective address• Effective Address SP
– Effective address can be any indexed addressing modes except an indirect indexed address
Ex: LEAS 6,SP SP+6 SPEx: LEAS 4,Y+ Y SP, and Y + 4 Y
LDS Load Stack pointer (M:M+1) SP• Loads MSB of the SP with the content of memory location
M and LSB of SP with contents of memory location M+1Ex: LDS #$3C00 3C:00 SPH:SPL
ECE 2510 67
Additional Stack Instructions
• STS Store Stack pointer– SP memory location– Store the contents of MSB of SP at the specified address and
contents of LSB of SP at the next higher byte addressSTS $1020 SPH:SPL $1020:$1021
• Transfer Instructions– TSX Transfer SP X or SPH:SPL XH:XL– TSY Transfer SP Y or SPH:SPL YH:YL– TXS Transfer X SP or XH:XL SPH:SPL– TYS Transfer Y SP or YH:YL SPH:SPL
ECE 2510 68
Additional Stack Instructions
CPS Compare Stack Pointer (SP) – (M:M+1)• Compares contents of SP with a 16-bit value at the address
specified and sets the CCR accordingly– Compare is accomplished internally by doing a 16-bit subtract of
(M:M-1) from the SP without modifying either SP or (M:M+1)
• Increment and decrement– DES Decrement Stack pointer SP-1 SP– INS Increment Stack Pointer SP+1 SP
ECE 2510 69
Parameter Passing to Subroutines
• Use registers– There aren’t many to choose from, but its fast and easy
• Use global memory– Assign global variables for all routines– Data is always in preplanned location (memory map)
• Use the stack– Push data onto the stack before the subroutine BSR or JSR– Relative offsets from the SP provide data (i.e. ldaa 2,SP)
• Use a stack frame– Extended version of the previous “Use the Stack”
ECE 2510 70
Passing with Stacks (1)
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
PC_LowByte
PC_HighByte $3BFAsubrou1:
...
...
...
rts
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
$3BFA
PC_HighByte:PC_LowByte PC
ldd #$1234pshdldx #4000pshxbsr subrou1pulxpuld
Setup Data and Call subroutine
Return
ECE 2510 71
Passing with Stacks (2)
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
PC_LowByte
PC_HighByte $3BFAsubrou1:
...
...
...
rts
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
$3BFA
PC_HighByte:PC_LowByte PC
ldd #$1234pshdldx #4000pshxbsr subrou1pulxpuld
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
$3BFA ldd #$1234pshdldx #4000pshxbsr subrou1pulxpuldnop
SP
$12
$00
$40
$34
$3C00
$3BFC
$3BFE
$3BFA
$40:00 X
$12:34 D
Return
Retrieve Data Registers
ECE 2510 72
Stack Frame
• Expand on the simple data passing approach– Incoming Parameters are pushed onto
the stack prior to a BSR or JSR– After the BSR or JSR, the subroutine
push all relevant registers (D, X, Y) to be restored prior to an RTS
– Additional space needed by the subroutine is allocated in the stack
– The stack pointer (SP) is set above all this so nested subroutines can be called.
• The stack frame is also called an activation record
Local variables
Saved registers
Return address
Incoming parameters
SP
Figure 4.9 Structure of the 68HC12 stack frame
ECE 2510 73
Example 4.11: Greatest Common Denominator (gcd) of two unsigned
Find the greatest common denominator (gcd) between to words, M and N.• Algorithm:• Step1:
– If M = N then M gcd, return to main program• Step2:
– If N < M then swap M and N• Step3:
– 1 gcd, if M = 1 or N = 1, return to main program• Step4:
– P = N % M (use IDIV … N/M and the remainder is P)• Step5:
– If (P = = 0) then M is the gcd, else M N, P M• Goto Step4
ECE 2510 74
GCD Example
• M=3575, N=2925 or M=$0DF7, N=$0B6D– N<M, swap N=$0DF7, M=$0B6D– N~=1 or M~=1 so keep going– P=N%M, N/M=1, Remainder=P=$028A– M→N, P→M, N=$0B6D,M =$028A– P=N%M, N/M=4, Remainder=P=$0145– M→N, P→M, N=$ 028A,M =$ 0145– P=N%M, N/M=2, Remainder=P=$0000– M is GCD = =$ 0145 or M=325
– Min/325=11 and Nin/325=9
ECE 2510 75
Example 4.11: GCD Subroutine
• Find the greatest common denominator (gcd) between to words, M and N.
• Use the main routine to set up and call the subroutine
• Use subroutine to perform the gcd algorithm– Use the stack to pass data to the
subroutine– Use the D register to return data– Protect the X register from being
changed by the subroutine
ECE 2510 76
GCD Code (2): Subroutine FirstFind_gcd: pshx ; save current X
Gcd_loop: ldd n_local,SP ; compute p= n % mldx m_local,SP ; n=D and m=Xidiv ; D/X X, Remainder → Dcpd #0 ; if result zero no factors, donebeq Done ; branch to done if no factorsmovw m_local,SP,n_local,SP ; m → nstd m_local,SP ; p → mbra Gcd_loop ; do it again
Done: ldd m_local,SP ; retrieve m, the current gcd
pulx ; restore Xrts ; return
$3BF8
$3BF6
Min.H
Nin.L
Nin.H
Return.L
Min.L
$3C00
$3BFE
Return.H
$3BFC
$3BFA
$3BF4
X.H
X.L
Input Variables and Temp Storage
Return Address
Protect X0, SP
4, SP
6, SP
2, SP
ECE 2510 77
GCD Code (1): Main Test Code
• Program: main Program.area program(abs)
M = 3575N = 2925M_local = 6N_local = 4
.org $1100gcd: .blkw 1.text_main::
lds #$3C00ldd #Mpshdldd #Npshdjsr Find_gcdstd gcdleas 4,SPswi
return address
contents of X
m_local
n_local
SP2 bytes
2 bytes
2 bytes
2 bytes
Figure 4.11 Stack frame of example 4.11
m_local: hold incoming m
n_local: hold incoming n
ECE 2510 78
Multi-Byte Division:Examples of Subroutine Calls
Multi Byte Division:• HCS12 instruction provides 16-bit by 16-bit signed and
unsigned instructions and also 32-bit by 16-bit signed and unsigned instructions– HCS12 does not have any instructions for higher precision
divisions
• Example: 32-bit by 32-bit unsigned division– Most popular method for higher precision divide operation is the
repeated subtraction method– The hardware for performing a repeated subtraction algorithm is as
shown in the next slide
ECE 2510 79
Multi Byte Division Flowchart
ALU
P register
R register Q register
set lsbshift left
write R
32-bit
32-bit 32-bitC
Controller
msb lsb
Figure 4.12 Conceptual hardware for implementing repeated subtraction method
Binary successive shift and divide (subtract)
ECE 2510 80
Multi Byte Division Algorithm Steps
• Before the division steps are performed, dividend and divisor must be loaded into register Q and register P respectively and register R must be cleared
• Step1:– Shift the register pair (R, Q) 1 bit left
• Step2:– Subtract the register P from register R (place in a temporary
buffer), put the result (temporary buffer) back to R if the result is non negative
• Step3:– If the result of step2 is negative, then set the least significant bit of
Q to 0, otherwise set the least significant bit of Q to 1
• Perform the procedure n times, then the quotient and the remainder will be left in registers Q and R
ECE 2510 81
Write a subroutine to implement the division algorithm that uses a repeated subtraction algorithm for the unsigned 32-bit dividend and divisor.
• The dividend and divisor are pushed into the stack.
• Space is allocated in the stack for this subroutine to return the quotient and remainder.
Solution: The stack frame is shown in Figure 4.12.
remainder
quotient
dividend
divisor
return address
[D]
[x]
[y]
Q
R
i
buf SP
SP+4
SP+5SP+
9
SP+21
SP+25
SP+29
SP+33
Figure 4.13 Stack frame for example 4.12
Example 4.12: Stack
ECE 2510 82
The Byte Level Stack Frame:
• The dividend and divisor are pushed into the stack.
• Space is allocated in the stack for this subroutine to return the quotient and remainder.
Example 4.12: Stack
remainder
quotient
dividend
divisor
return address
[D]
[x]
[y]
Q
R
i
buf SP
SP+4
SP+5SP+
9
SP+21
SP+25
SP+29
SP+33
Figure 4.13 Stack frame for example 4.12
ECE 2510 83
Multi Byte Division Algorithm Steps
• Before JSR: leave space for remainder and quotient, push dividend and divisor
• In JSR: protect resisters D, X, and Y• dividend and divisor loaded into register
Q and register P (divisor in place) respectively
• Register R must be cleared• Step1:
– Shift the register pair (R, Q) 1 bit left• Step2:
– Subtract the register P from register R, put the result in buf and then back to R if the result is non negative
• Step3:– If the result of step2 is negative, then set
the least significant bit of Q to 0, otherwise set the least significant bit of Q to 1
• Perform the procedure n times, then the quotient and the remainder will be left in registers Q and R
ECE 2510 84
buf = 0 ; distance of buf from the top of the stacki = 4 ; distance of i from the top of the stackR = 5 ; distance of R from the top of the stackQ = 9 ; distance of Q from the top of the stacklocal = 13 ; number of bytes for local variablesdivisor = 21 ; distance of divisor from the top of the stackdividend = 25 ; distance of dividend from the top of the stackquotient = 29 ; distance of quotient from the top of the stackremainder = 33 ; distance of remainder from the top of the stackdvdend_hi = $42 ; dividend to be testeddvdend_lo = $4c15 ; "dvsor_hi = $0 ; divisor to be testeddvsor_lo = $64 ; ".org $1100quo: .blkb 4 ; memory locations to hold the quotientrem: .blkb 4 ; memory locations to hold the remainder
Multi Byte Division Code(1)
remainder
quotient
dividend
divisor
return address
[D]
[x]
[y]
Q
R
i
buf SP
SP+4
SP+5SP+
9
SP+21
SP+25
SP+29
SP+33
Figure 4.13 Stack frame for example 4.12
ECE 2510 85
.text_main:: ; starting address of the program
lds #$3C00 ; initialize stack pointerleas -8, sp ; make a hole of 8 bytes to hold the resultldd #dvdend_lopshdldd #dvdend_hipshdldd #dvsor_lopshdldd #dvsor_hipshdjsr div32 ; call the divide subroutineleas 8, sp
; the following 4 instructions get the quotient from the stackpuldstd quopuldstd quo+2
; the following 4 instructions get the remainder from the stackpuldstd rempuldstd rem+2swi
Multi Byte Division Code(2): main
remainder
quotient
dividend
divisor
return address
[D]
[x]
[y]
Q
R
i
buf SP
SP+4
SP+5SP+
9
SP+21
SP+25
SP+29
SP+33
Figure 4.13 Stack frame for example 4.12
ECE 2510 86
remainder
quotient
dividend
divisor
return address
[D]
[x]
[y]
Q
R
i
buf SP
SP+4
SP+5SP+
9
SP+21
SP+25
SP+29
SP+33
Figure 4.13 Stack frame for example 4.12
div32: pshd ; 32-bit divide subroutinepshx ; push the original registerspshyleas -local, spldd #0std R, sp ; initialize register R to 0std R+2, spldd dividend, spstd Q, sp ; place dividend in register Qldd dividend+2, spstd Q+2, spldaa #32staa i, sp ; initialize loop count
loop: lsl Q+3, sp ; shift register pair Q and R to the leftrol Q+2, sp ; by 1 bitrol Q+1, sp ; "rol Q, sp ; "rol R+3, sp ; "rol R+2, sp ; "rol R+1, sp ; "rol R, sp ; "
Multi Byte Division Code(3): sub
ECE 2510 87
; the following 8 instructions subtract the divisor from register Rldd R+2, sp ; 2 LSB firstsubd divisor+2, spstd buf+2, spldaa R+1, sp ; 3 bytesbca divisor+1, spstaa buf+1, spldaa R, sp ; MSBsbca divisor, sp ; carry defines if borrow neededbcs smaller ; if smaller, do not store result (don’t keep buf)
; the following 6 instructions store the difference back to R registerstaa R, spldaa buf+1, spstaa R+1, spldd buf+2, spstd R+2, spldaa Q+3, sporaa #01 ; set the least significant bit of Q register to 1staa Q+3, spbra looptest
Multi Byte Division Code(4)
ECE 2510 88
smaller: ldaa Q+3, spanda #$FE ; set the least significant bit of Q register to 0staa Q+3, sp
looptest: dec i, splbne loop
; the following 4 instructions copy the final remainder R into the remainder stack frameldd R, spstd remainder, spldd R+2, spstd remainder+2, sp
; the following 4 instructions copy the final quotient Q into the quotient stack frameldd Q, spstd quotient, spldd Q+2, spstd quotient+2, sp
leas local, sp ; deallocate local variablespuly ; pull the originally stored registerspulxpuldrts
Multi Byte Division Code(5)
ECE 2510 89
Bubble Sorting
Bubble Sort• Sorting is the most common ingredients of programming
– Sorting makes many efficient search methods possible– Arranging a group of elements in an order
(ascending/descending/alphabetical) is known as sorting
• Bubble sort is a widely known sorting method– Basic idea of bubble sort is to go through the array sequentially
several times– Each iteration consists of comparing each element in the array with
its successor and interchanging the two elements if they are not in proper order
• Notice that the last element in the array is correct after each pass!
ECE 2510 90
Bubble Sort Sequence Example
Ex: 157, 13, 35, 9, 98, 810 (arrange in ascending order)• Iteration1:
– compare 157 and 13 since 157 > 13 interchange the values 13, 157, 35, 9, 98, 810
– Compare 157 and 35 157 > 35 13, 35, 157, 9, 98, 810– Compare 157 and 9 157 > 9 13, 35, 9, 157, 98, 810– Compare 157 and 98 157 > 98 13, 35, 9, 98, 157, 810
Compare 157 and 810 157 < 810 13, 35, 9, 98, 157, 810
• Iteration2: Start with 1st element of array and compare with remaining array elements through N-1
• Perform the iteration till only the first two elements of the array are compared
ECE 2510 91
array_x
N
return address
B
A
Y
X
buf
in_order
inner
iteration SP
Figure 4.15 Stack frame for bubble sort
SP+1
SP+2
SP+3
SP+12
SP+13
Example 4.13: Bubble Sort
• Example 4.13 Write a subroutine to implement the bubble sort algorithm and a sequence of instructions for testing the subroutine. – Pass the base address of the array and the
array count in the stack.– Protect all registers once inside the
subroutine– Four bytes are needed for local variables.
– The stack frame meeting the description and shown will be used by the subroutine
ECE 2510 92
array_x
N
return address
B
A
Y
X
buf
in_order
inner
iteration SP
Figure 4.15 Stack frame for bubble sort
SP+1
SP+2
SP+3
SP+12
SP+13
Example 4.13: Bubble Sort
• Example 4.13 – Pass the base address of
the array and the array count in the stack.
– Protect all registers once inside the subroutine
– Four bytes are needed for local variables.
– The stack frame meeting the description and shown will be used by the subroutine
$3BF8
$3BF6
array_x.H
N
Return.L
array_x.L
$3C00
$3BFE
Return.H
$3BFC
$3BFA
$3BF4
D.H or A
D.L or B
Array Address
Return Address
Protect D (A:B)
0, SP
12, SP
13, SP
2, SP
Array Count
X.L
X.HProtect X
Protect YY.L
Y.H
buf
In_order
inner
iteration
$3BF2
$3BF1
1, SP
3, SP
ECE 2510 93
Star
t
itera
tion
N -
1
in_o
rder
1in
ner
itera
tion
yes
swap
arr
ay[i
] &
arr
ay[i
+1]
arra
y[i]
> a
rray
[i+1
]?
in_o
rder
0
inne
rin
ner
- 1
inne
r =
0?
i0
ii +
1
yes
no
no
in_o
rder
= 1
?ye
s
no
itera
tion
itera
tion
- 1
itera
tion
= 0?
Stop
no
yes
Figu
re 4
.14
Log
ic fl
ow o
f bub
ble
sort
Example 4.13 Flow Diagram
ECE 2510 94
arr equ 13 ; distance of the variable arr from stack toparcnt equ 12 ; distance of the variable arcnt from stack topbuf equ 3 ; distance of local variable buf from stack topin_order equ 2 ; distance of local variable in_order from stack topinner equ 1 ; distance of local variable inner from stack topiteration equ 0 ; distance of local variable iteration from stack toptrue equ 1false equ 0n equ 30 ; array countlocal equ 4 ; number of bytes used by local variables.org $1000array_x: .byte 3,29,10,98,54,9,100,104,200,92,87,48,27,22,71
.byte 1,62,67,83,89,101,190,187,167,134,121,20,31,34,54.text_main:: lds #$3C00 ; initialize stack pointer
ldx #array_xpshx ; push array pointer, arrldaa #npsha ; push arcnt or Njsr bubbleleas 3, sp ; deallocate space used by outgoing parametersswi ; break to D-Bug12 monitor
Example 4.13: Code(1)
array_x
N
return address
B
A
Y
X
buf
in_order
inner
iteration SP
Figure 4.15 Stack frame for bubble sort
SP+1
SP+2
SP+3
SP+12
SP+13
ECE 2510 95
bubble: pshd ; push incoming registerspshypshxleas -local, sp ; allocate space for local variables
ldaa arcnt, sp ; compute the number of iterations to be performeddeca ; "staa iteration, sp ; “
ploop: ldaa #true ; set array in_order flag to true before any iterationstaa in_order, sp ; "ldx arr, sp ; use index register X as the array pointerldaa iteration, sp ; initialize inner loop count for each iterationstaa inner, sp ; "
Example 4.13: Code(2)
ECE 2510 96
cloop: ldaa 0,x ; compare two adjacent elementscmpa 1,x ; "bls looptest ; if 0<1 keep the order and continue
; the following five instructions swap the two adjacent elementsstaa buf, sp ; swap two adjacent elementsldaa 1,x ; "staa 0,x ; "ldaa buf, sp ; "staa 1,x ; "ldaa #false ; reset the in-order flagstaa in_order, sp ; “
looptest: inxdec inner, spbne cloop ; repeat until all pairs tested
Example 4.13: Code(3)
ECE 2510 97
tst in_order, sp ; test array in_order flag after each iterationbne done ; if no change made, the algorithm is finisheddec iteration, spbne ploop ; if the maximum iterations are complete, done
done: leas local, sp ; deallocate local variablespulx ; restore the registerspulypuldrts ; return
Example 4.13: Code(4)
ECE 2510 98
C Code Example of Bubble Sort Algorithm
• C Code Example:For (I = 0; I < n-1; i++){For (J = i+1; J < n; J++)
{If (array[i] > array[j]) then
{Temp = array[i];array[i] = array[j];array[j] = temp;}
}}
ECE 2510 99
Functions in C
• A function provides a convenient way to encapsulate some computation. Once encapsulated, the function can be used without concern for the implementation.–Ignore how a job is done, focus on what is accomplished … trusting that the output based on the inputs will be correct.
• C Function definitionReturn-type function-name (parameter declaration, if any){
declarationsstatements
}
• Note: all C functions are pass by value … but
ECE 2510 100
Function Parameters
• Arguments: Pass by value– Defined so that the original values in the calling software are not
changed by the called function.• Implementation, all values are copied to a new location for the
function to use. Local copies can be altered by the function.
• Define globally– If an extern variable can be defined and used, the function will be
use the global argument and it can be modified by the function. (Pass by global memory)
• Arguments: Pass by pointer value– Defined so that the address to a value is provided.
(Pass by reference)• Particularly useful when sending arrays, such as data or text.• Access to the original values is allowed, so changed can be directly
made.
ECE 2510 101
Assembly Language Implementation
• C compilers must convert the high-level language into machine language. But, the machine language is readable in assembly language.– Passing is based on the compiler and the machine– Therefore, we define parameter passing in assembly language
• Section 4.7.1 Parameter Passing– Use Registers– Use Stacks– Use global memory
ECE 2510 102
Compiler Implementation
• Can a C compiler assume that there are enough registers to pass arguments by value?– No.– What other option is there? Use global memory or use stacks.
• Can all passed values be assigned as unique global addresses (remember that pass by value passes a copy)– Yes, but that’s a lot of memory that may or may not be used!– What other option is there? Use stacks.
• The preferred approach for passing values at the assembly and machine level is pass using the stack.– Stack frames provide copies of the original data, temporary storage
that can reclaimed (no permanent global), and it can easily store values or pointers for use.
ECE 2510 103
C Code Examples of Alternate Bubble Sort Algorithm
• C Code Example:For (I = 0; I < n-1; i++){For (J = i+1; J < n; J++){If (array[i] > array[j]) then{Temp = array[i];array[i] = array[j];array[j] = temp;}}}
• C Code Example:For (I = 0; I < n-1; i++){For (J = i+1; J < n; J++){If (array[i] > array[j]) then{swap(& array[i] ,& array[j]);}}}
void swap(int *px, int *py){int temp;temp=*px;*px=*py;*py=temp;}
ECE 2510 104
• One of the methods for finding the square root of an integer is based on the following equation:
– Equation 4.1 can be transformed into
– For n, the integer value closest to the square root of q
– The algorithm for finding the square root of an integer based on equation 4.2 is illustrated in the flowchart shown in Figure 4.16.
Finding the Square Root (1 of 2)
22
1 21
0
nnnnin
i
1
0
1
0
1
0
1
0
2 12212n
i
n
i
n
i
n
i
iiinn
ECE 2510 105
Examples of Subroutine Calls
Ex: Compute the square root of q• Let n be the integer value that’s closest to the true square
root• One of the following relationship will be satisfied
N2 < qN2 = qN2 > q
• The logic flow shown in the next slide can be used to find the square root of a number
ECE 2510 106
Start
i 0sum 0
sum sum + (2i + 1)
sum < q?
i i + 1
yes
sq_root i
Stop
Figure 4.16 Algorithm for finding the square root of integer q.
no
Finding the Square Root (2 of 2)
ECE 2510 107
q_ val
re turn address
[Y]
i_ lo cal
sum
SP
SP + 2
SP + 1 0
Figure 4 .1 7 Stack fram e o f exam ple 4 .1 4
Example 4.14: Square Root
• Example 4.14 Write a subroutine to implement the square root algorithm. This subroutine should be able to find the square root of a 32-bit unsignedinteger. The parameter is pushed onto the stack and the square root is returned in accumulator D.
• Solution: The stack frame is shown in Figure 4.17. The subroutine and the instruction sequence for testing the subroutine is shown in the following pages.
ECE 2510 108
Examples of Subroutine Calls
• This subroutine will find the exact square root if the given number has one
• If the given number does not have an exact square root, then the number returned by the subroutine may not be the closest approximation– The algorithm in the previous slide will stop only when sum > q– This algorithm may have an undesirable effect that the last i value
may not be as close to the real square root as is value i-1– Can be fixed by comparing the following two expressions– I2 with q_val, if smaller then I is a better choice– Q_val with (I-1)2 then i-1 is a better choice
ECE 2510 109
q_hi equ $000F ; upper word of qq_lo equ $4240 ; lower word of qi_local equ 0 ; distance of local variable i from the top of the stack sum equ 2 ; distance of local variable sum from the top of the stack q_val equ 10 ; distance of incoming parameter q from the top of stack local equ 6 ; number of bytes allocated to local variables.org $1100sq_root .blkb 2 ; to hold the square root of q
.text_main::
lds #$3C00ldd #q_lopshdldd #q_hipshdjsr findSqRootstd sq_rootleas 4,spswi
Example 4.14: Code (1)
q_ val
re turn address
[Y]
i_ lo cal
sum
SP
SP + 2
SP + 1 0
Figure 4 .1 7 Stack fram e o f exam ple 4 .1 4
ECE 2510 110
findSqRoot:pshy ; save y in the stackleas -local,sp ; allocate local variablesldd #0 ; initialize local variable i to 0std i_local,sp ; "std sum,sp ; initialize local variable sum to 0std sum+2,sp ; “
loop: ldd i_local,spldy #2emul ; compute 2i D * Y = Y:Daddd sum+2,sp ; add 2i to sum LSWordstd sum+2,sptfr y,dadcb sum+1,sp ; add 2i to sum 3rd Bytestab sum+1,spadca sum,sp ; add 2i to sum MSBstaa sum,sp
Example 4.14: Code (2)
ECE 2510 111
; add 1 to sum (need to propagate carry to the most significant byte of sum)ldaa #1adda sum+3,spstaa sum+3,spldaa sum+2,spadca #0staa sum+2,spldaa sum+1,spadca #0staa sum+1,spldaa sum,spadca #0staa sum,sp ; finish adding 1 to sum
ldd i_local,sp ; increment i by 1addd #1 ; “std i_local,sp
Example 4.14: Code (3)
ECE 2510 112
; compare sum to q_val by performing subtraction (need consider borrow)ldd sum+2,spsubd q_val+2,spldaa sum+1,spsbca q_val+1,spldaa sum,spsbca q_val,splblo loop ; if result less than q, keep going
ldd i_local,sp ; place sq_root in D before return
exit: leas local,sp ; deallocate space used by local variablespulyrts ; return
Example 4.14: Code (4)
ECE 2510 113
Tips for Debugging Programs Involving Subroutine Calls
• What to do when the program gets stuck?– Step 1
• Find out which subroutine gets stuck by setting a breakpoint immediately after the jsr or bsr instruction.
– Step 2• Find out why the subroutine gets stuck.• Forgetting to restore registers pushed onto the stack before return.• Forgetting to deallocate local variables before return.• There are some infinite loops in the subroutine.• Calling other subroutines that do not return.
ECE 2510 114
General Debugging Strategy
• Make sure all leaf subroutines work correctly by using the methods described in Section 2.9.– Test the subroutine the it’s own special calling program– Work from the bottom up
• Debug intermediate subroutines. Make sure no intermediate subroutines get stuck.
• Debug the top level program.– Use D-Bebug12 to monitor program progress– Use terminal I/O to write progress characters to the screen
ECE 2510 115
D-Bug12 Functions Available to supportPerforming I/O
Chap. 4.10 p. 161
ECE 2510 116
D-Bug12 Functions to Perform I/O
• D-Bug12 monitor provides a few subroutines to support I/O operations– I/O routines can be utilized to facilitate program developments on
a demo board that contains the D-Bug12 monitor
• User accessible routines are written in C– The first parameter is passed to the function in the D accumulator– All others are passed to the user callable functions on the stack– Parameters are pushed in the reverse order they are listed in the
function declaration
ECE 2510 117
User Accessible Utility Functions
Note: far subroutines must use CALL others use JSR
ECE 2510 118
D-Bug 12 Function Assembly Language Call or JSR in ICC12
• All subroutine calls use indexed indirect addressing– [$XX, xysp] or [D, xysp]
• The textbook reference to “PCR” is not available in ICC12– The assembler does not recognize the name
• Therefore, use one of the following constructs– Ex1:
Ldx #getchrJsr [0,x]
– Ex2:Ldy #0Call [out2hex, y]
ECE 2510 119
D-Bug12 Functions Parameter Passing
• Parameter Restrictions– Parameters of type char must be converted to an integer– Parameters of type char will occupy the lower order byte of a word
pushed onto the stack, or accumulator B if the parameter is passed in D accumulator
– All 8-bit and 16-bit function values are returned in accumulator D– A value of type char returned in accumulator D is located in the 8-
bit accumulator B
• None of the CPU registers contents, except the stack pointer, are preserved by the called functions– Register values needs to be pushed onto the stack before any
parameters have been pushed onto the stack and should be restored after de-allocating the parameters
ECE 2510 120
Calling D-Bug12 Functions from Assembly
• Calling the functions from assembly involves– Pushing the parameters onto the stack in the proper order– Loading the first or only function parameter into accumulator D– Calling the D-Bug12 function with a JSR instruction– Code following the JSR instruction should remove any parameters
pushed onto the stack
• Addressing mode used in the JSR instruction is Indexed Indirect Addressing Mode
Ex: Ldx #getchrJSR [0,x] indirect addressing to the addressed pointed to by getchr
ECE 2510 121
Terminal Functions (keyboard & monitor)
• Basic IO functions– For C, normally included in the stdio library– For assembly, use the jsr or call formats described with the indirect
addresses mode defined before. (a jump table to the subroutine)
Function Description Pointer Address
getchar() Get a character from SCI0 or SCI1 $EE84 putchar() Send a character out SCI0 or SCI1 $EE86 printf() Formatted Output - Translates binary values to characters $EE88 far GetCmdLine() Obtain a line of input from the user $EE8A
ECE 2510 122
getchar
Int getchar (void)• Pointer Address: $EE84
– This function receives a single character from the control terminal (Serial Communication Interface or keyboard)
– The character is returned as an integer, the 8-bit character is placed in accumulator B
ECE 2510 123
Example of getchar Function
• Ex:Getchar = $EE84------Ldy #charstackLdx #0pshyJsr [Getchar,x]pulyStab 1,y+------------
• This code will wait until a character is typed on the keyboard, read the character, and then return.
ECE 2510 124
putchar
Int putchar(int)• Pointer Address: $EE86
– This function outputs a single character to the control terminal Serial Communication interface
Ex:Putchar = $EE86--------Ldd #$32Ldy #putchrJsr [0, y]---
• Output one ASCII character to the terminal (‘2’ is printed)
ECE 2510 125
printf
Int printf(char *format,----------)• Pointer Address: $EE88
– This function is used to convert, format and print its argument on the standard output monitor or LCD under the control of the format string pointed to by format.
– All except floating-point data types are supported.
• The format string contains two basic types of objects: – ASCII characters which will be copied directly to the display
device.– Conversion specifications. Each conversion specification begins
with a percent sign (%).
ECE 2510 126
printf: Example 1
printf = $EE88prompt: .asciz “Flight Simulation\n”----ldd #promptldx #0jsr [printf, x]--------
• This instruction sequence will cause the message “Flight Simulation” to be displayed and cursor will be moved to the beginning of next line.
ECE 2510 127
printf: Example 2
printf = $EE88 ; printf subroutine addressCR = $0DLF = $0A
.org $1000prompt: .ascii "The Greatest Common Divisor of %d and %d is %d."
.byte CR,LF,0
pgcd: ; print the gcd string to the terminalpshxldd gcd ; pass data on the stackpshdldd #N ; pass data on the stackpshdldd #M ; pass data on the stackpshdldd #promptldx #printfjsr [0,x] ; call the printf subroutineleas 6,SPpulx
ECE 2510 128
printf: Numerical Conversion Characters
• This set is universal to applications based on C (e.g. MATLAB)
Table 4.4 Printf() conversion characters
d, ioxXucsp%
character Argument type; displayed as
int; signed decimal numberint; unsigned octal number (without a leading zero)int; unsigned hex number using abcdef for 10...15int; unsigned hex number using ABCDEF for 10...15int; unsigned decimal numberint; single characterchar *; display from the string until a '\0' (NULL)void *; pointer (implementation-dependent representation)no argument is converted; print a %
ECE 2510 129
Printf: Number Formatting
• Conversion specifications. Each conversion specification begins with a percent sign (%).
• Optional formatting characters may appear between the percent sign and ends with a single conversion character in the following order:[-][<FieldWidth>][.][<Precision>][h | l]
Table 4.3 Optional formatting characters
Character Description
-(minus sign)FieldWidth
. (period)Precision
hl(letter ell)
Left justifies the converted argument.Integer number that specifies the minimum field width for the convertedarguemnt. The argument will be displayed in a field at least this wide.The displayed argument will be padded on the left or right if necessary.Separates the field width from the precision.Integer number that specifies the maximum number of characters todisplay from a string or the minimum number of digits for an intger.To have an integer displayed as a short.To have an integer displayed as a long.
ECE 2510 130
printf Example 2
• Suppose labels m, n and gcd represent three memory locations and gcd holds greatest common divisor and m ,n represent the two numbers
printf = $EE88prompt .asciz “The Greatest Common Divisor of %d and %d is %d.\n”…ldd gcdpshdldd #npshdldd #mpshdldd #promptjsr [printf,x]leas 6,SP
Note: 4 values sent to the subroutine: prompt address (in D reg), M, N, and gcd (on stack)
ECE 2510 131
GetCmdLine
Int far GetCmdLine(char *cmdLineStr, int CmdLineLen)• Pointer Address: $EE8A
– This function is used to get line of input from the user– GetCmdLine accepts inputs from the user one character at a time
by calling getchar() function– The received characters are placed in the character array pointed
by the cmdLineStr using putchar() instruction– A maximum of CmdLineLen-1 characters may be entered– Only printable ascii characters are accepted as inputs
ECE 2510 132
GetCmdLine Example
Printf = $EE88GetCmdLine = $EE8A
Prompt: .asciz “Please Enter a String\n”Inbuf: .blkb 100Cmdlinelen: .byte 100
…ldd #Promptldx #0jsr [printf, x]ldd #Cmdlinelenpshdldd #Inbufldx #0call [GetCmdLine, x]
ECE 2510 133
Special Value Manipulation Strings
• Basic IO functions– For C, normally included in the stdlib, ctype or string libraries
see appendix B in Kernighan & Ritchie– For assembly, use the jsr or call formats described with the indirect
addresses mode defined before. (a jump table to the subroutine)
Function Description Pointer Address
strlen() Returns the length of a null terminated string $EE98 strcpy() Copies a null terminated string $EE9A toupper() Converts lower case characters to upper case $EE94 isalpha() Checks for membership in the set [a..z, A..Z] $EE96 isxdigit() Checks for membership in the set [0..9, a..f, A..F] $EE92 Previous Code Example far sscanhex() Convert an ASCII hexadecimal string to 16-bit integer $EE8E far out2hex() Displays 8-bit number as 2 ASCII hex characters $EE9C far out4hex() Displays 16-bit number as 4 ASCII hex characters $EEA0
ECE 2510 134
toupper
Int toupper(int c)• Pointer Address: $EE94
– If c is a lowercase character, toupper() will return the corresponding uppercase letter
– If the character is in uppercase, it simply returns c
• Example:toupper = $EE94
c_buf: .asciz “a”…ldab c_bufclraldx #0jsr [toupper,x]
ECE 2510 135
isalpha
Int isalpha(int c)• Pointer Address: $EE96
– This function tests the character passed in c for membership in character set (a-z, A-Z)
– If the character c is in this set, the function returns a non-zero value, else returns a zero value
– This function is useful for validating an input string• Example:
Isalpha = $EE96c_buf: .ascii “b”
…ldab c_bufclraldx #0jsr [isalpha,x]
ECE 2510 136
strlen
Unsigned int strlen(const char *cs)• Pointer Address: $EE98
– The strlen() function returns the length of the string pointed to by cs
• Example:strlen = $EE98
cs: .asciz “----------------------------------”…ldd #csldx #0jsr [strlen,x]
ECE 2510 137
strcpy
Char *strcpy(char *s1, char *s2)• Pointer Address: $EE9A
– This function copies the string pointed to by s2 into the string pointed to by s1
• Example:strcpy = $EE9A
S2: .asciz “--------------------------”S1: .blkb ---
…ldd #S2pshdldd #S1ldx #0jsr [strcpy,x]leas 2,SP
ECE 2510 138
out2hex
Void far out2hex(unsigned int num)• Pointer Address: $EE9C
– This function displays the lower byte of num on the terminal screen as two hex characters. The upper byte of num is ignored.
– Binary to hex printed characters
• Example:out2hex = $EE9C.org $1000data: .byte 20
…ldab dataclraldx #0call [out2hex, x]
ECE 2510 139
out4hex
Void far out4hex(unsigned int num)• Pointer Address: $EEA0
– This function displays the num on the terminal screen as four hex characters.
– Binary to hex printed characters
• Example:out4hex = $EEA0.org $1000data: .word 20
…ldd dataldx #0call [out4hex, x]
ECE 2510 140
Finding Prime Number: Example 4.15
• Write a program that invokes appropriate functions to find the prime number between 1000 and 2000. Output eight prime numbers in one line.
• To do this, you will need to – Write a subroutine to test if an integer is a prime.– Invoke the printf() function to output the prime number.– Write a loop to test all the integers between 1000 and 2000.
ECE 2510 141
Prime Number Main Process
• Step 1– Output the message “The prime numbers between 1000 and 2000
are as follows:”.
• Step 2– For every number between 1000 and 2000
• call a test_prime subroutine/function to see if it is a prime.• output the number (call printf()) if it is a prime.• if there are already eight prime numbers in the current line, then also
output a carriage return.• Once the upper bound is reached stop, providing a carriage return to
the output
ECE 2510 142
Testing for a Prime Number
• A prime number (num) has only one and itself as factors• Perform division by 2 to some limit, if the remainder is
zero, the value is a factor and the number is not prime.• The maximum limit for testing is num/2
– Since 2 will be tested, numbers greater than 2 x number are larger than the prime number
– Check all numbers from 2 to a num/2
ECE 2510 143
SP
num
return address
[X]
prime_flag
ilimit
iSP + 2
SP + 4
SP + 9
Figure 4.18 Stack frame for the prime test subroutine
The Process for test_prime
• Step 1: setup– Let num, i, and isprime represent the
number to be tested, the loop index, and the flag to indicate if num is prime.
– Let ilimit indicate the maximum prime value to check for num
• Step 2: initialization– isprime = 0;– Ilimit = num/2
• Step 3– For i = 2 to ilimit do
if num % i = 0 then return; else isprime = 1; return;
i.L
i.H
$3BF8
$3BF6
num.H
Return.L
num.L
$3C00
$3BFE
Return.H $3BFC
$3BFAX.H
isprime
ilimit.L
X.L
Input Variables and Temp Storage
Return Address
Protect X
0, SP
4, SP
9, SP
2, SP
Prime Flag
Limit for Testingilimit.H
Loop Test Index$3BF5
$3BF7
7, SP
$3BF9
ECE 2510 144
Example 4.15 (1): EquatesCR = $0DLF = $0Ai = 0 ; distance of variable i from stack topilimit = 2 ; distance of variable ilimit from stack topprime_flag = 4 ; distance of variable isprime from stack topnum = 9 ; distance of variable num from the stack topplocal = 5 ; number of bytes allocated to local variablesupper = 2000 ; upper limit for testing primelower = 1000 ; lower limit for testing primeprintf = $EE88 ; location where the address of printf() is stored
ECE 2510 145
Example 4.15 (2): Input/Output Memory
.org $1000formmat0: .byte CR,LF
.ascii "The prime numbers between %d and %d are as follows:"
.byte CR,LF,CR,LF,0format1: .asciz " %d "format2: .ascii " "
.byte CR,LF,0.org $1100out_buf: .blkb 10prime_cnt: .blkb 1k: .blkb 2 ; the main loop prime valuetemp: .blkb 2
ECE 2510 146
Example 4.15 (3): Initialization
.text_main::
lds #$3C00 ; initialize the stack pointerldx #upperstx temp ; initialize temp to 2000 for prime testingpshx ; push for printingldx #lowerstx k ; initialize k to 1000 for prime testingpshx ; push for printingldd #format0 ; print the intro lineldy #0jsr [printf, y]leas 4,sp ; restore sp to the correct locationclr prime_cnt ; clear the counter
ECE 2510 147
Example 4.15 (4): main programagain:
ldd kcpd #upperbhi stop ; stop when k is greater than upperpshd ; push k as the number to testjsr prime_tst ; test if k is primeleas 2,sp ; deallocate space used by outgoing parameterststb ; prime flag returned in D registerbeq next_k ; test next integer if flag=0, i.e. k is not prime
inc prime_cnt ; increment the prime countldd kpshd ; pass k for printingldd #format1 ; use format 1 for the print of kldy #0jsr [printf, y] ; output kleas 2,sp ; deallocate space used by outgoing parametersldaa prime_cntcmpa #8 ; are there 8 prime numbers in the current line?blo next_k ; if not, skip the next section
ECE 2510 148
Example 4.15 (5): main program; output a CR, LF if there are already 8 prime numbers in the current line
ldd #format2 ; load format2 to provide a CR, LFldy #0jsr [printf, y]clr prime_cnt
next_k:ldx kinxstx kbra again
stop:ldd #format2 ; load format2 to provide a CR, LF at the endldy #0jsr [printf, y]swi
ECE 2510 149
Example 4.15 (6): prime_tst - initprime_tst:
pshxleas -plocal, sp ; allocate local variableldaa #1staa prime_flag, sp ; set the flag to trueldd num, spcpd #1beq not_prime ; 1 is not a prime numbercpd #2beq is_prime ; 2 is a prime numberlsrd ; compute num/2 as the test limitstd ilimit, sp ; "ldd #2std i,sp ; set first test number to 2
ECE 2510 150
Example 4.15 (7): prime_tst - loop
test_loop:ldx i, spldd num, spidivcpd #0 ; if num can be divided by i, thenbeq not_prime ; it is not a primeldd i, spcpd ilimit, spbeq is_prime ; num is prime at the end of test loopldx i, spinxstx i, spbra test_loop
not_prime:clr prime_flag,sp
is_prime:ldab prime_flag,sp ; put the result in Bleas plocal,sppulxrts
ECE 2510 151
>g 122AThe prime numbers between 1000 and 2000 are as follows:
1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 1999
User Bkpt EncounteredPP PC SP X Y D = A:B CCR = SXHI NZVC
Program Execution Results
ECE 2510 152
Finding Prime Number: Example 5.2 and 5.1
• Write a program that invokes appropriate functions to count the prime number between 100 and 1000.
• To do this, you will need to – Write a subroutine to test if an integer is a prime.– Invoke the printf() function to output the prime number count.– Write a loop to test all the integers between 100 and 1000.
ECE 2510 153
Example 5.2: main program
#include <stdio.h>char test_prime (int a); /* prototype declaration for the function test_prime */main ( ){
int i, prime_count = 0;for (i = 100; i <= 1000; i++) {
if (test_prime(i))prime_count ++;
}printf(“\n The total prime numbers between 100 and 1000 is %d\n”, prime_count);
}
• Function prototype declaration allows us to call a function before it is defined.
• Syntax of a function prototype declaration:return_type function_name (declarations of arguments);
• Now we need the function
ECE 2510 154
Example 5.1: test_prime function
/* this function returns a 1 if a is prime. Otherwise, it returns a 0. */
char test_prime (int a){
int i;if (a = = 1) return 0;for (i = 2; i < a/2; i++)
if ((a % i) = = 0) return 0;return 1;
}
ECE 2510 155
Example 5.3: Bubble Sort Function:Pointers and Addresses
void swap (int *px, int *py); /* function prototype declaration */void bubble (int a[], int n) /* n is the array count */{
int i, j;for (i = 0; i < n - 1; i++)
for (j = n - 1; j > i; j--)if (a[j - 1] > a[j])
swap (&a[j - 1], & a[j]);}
void swap(int *px, int *py){
int temp;temp = *px;*px = *py;*py = temp;
}
ECE 2510 156
Chapter 5 Notes
• Chapter 5 provides and overview of C-programming– If you are still weak in C, read through the chapter
• Chapter 5 notes on C programming are on line