Chapter 4 Advanced Assembly Programming. Introduction Program = data structures + algorithm Data...

81
Chapter 4 Advanced Assembly Programming
  • date post

    21-Dec-2015
  • Category

    Documents

  • view

    224
  • download

    0

Transcript of Chapter 4 Advanced Assembly Programming. Introduction Program = data structures + algorithm Data...

Chapter 4

Advanced Assembly Programming

top element

bottom element

low address

high address

Stack pointer

Figure 4.1 Diagram of the HCS12 stack

Introduction • 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

Table 4.1 HCS12 push and pull instructions and their equivalent load and store instructions

Mnemonic

pshapshbpshcpshdpshxpshypulapulbpulcpuldpulxpuly

Function

push A into the stackpush B into the stackpush CCR into the stackpush D into stackpush X into the stackpush Y into the stackpull A from the stackpull B from the stackpull CCR from the stackpull D from the stackpull X from the stackpull Y from the stack

Equivalent instruction

staa 1, -SPstab 1, -SPnonestd 2, -SPstx 2, -SPsty 2, -SPldaa 1, SP+ldab 1, SP+noneldd 2, SP+ldx 2, SP+ldy 2, SP+

HCS12 Support for the Stack Data Structure

• A 16-bit stack pointer (SP)• Instructions and addressing mode

-

Indexable Data Structures• Vectors and matrices are

indexable data structures.• The first element of a vector is

associated with the index 0 in order to facilitate the address calculation.

• Assemblers directives db, dc.b, dc.b are used to define arrays of 8-bit elements.

• Assemblers directives dw, dc.w, and fdb are used to define arrays of 16-bit elements.

• 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.

• Solution:– Use the double accumulator 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.• Need to compare key with

every array element because it is not sorted.

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

N equ 30 ; array countnotfound equ -1key equ 190 ; define the searching key

org $1000result rmw 1 ; reserve a word for result  org $1500 ; 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 swivec_x dw 13,15,320,980,42,86,130,319,430,4, 90,20,18,55,30,51,37

dw 89,550,39, 78,1023,897,930,880,810,650,710,300,190end

Binary Search

• Step 1– Initialize variables max and min to n -1 and 0, respectively.

• Step 2– If max < min, then stop. No element matches the key.

• Step 3– Let mean = (max + min)/2

• Step 4– If key = arr[mean], then key is found in the array, exit.

• Step 5– If key < arr[mean], then set max to mean - 1 and go to step 2.

• Step 6– If key > arr[mean], then set min to mean + 1 and go to step 2.

Example 4.3 Write a program to implement the binary search algorithm and also a sequence of instructions to test it.

Solution:n equ 30 ; array countkey equ 69 ; key to be searched

org $1000max ds.b 1 ; maximum index value for comparisonmin ds.b 1 ; minimum index value for comparisonmean ds.b 1 ; the average of max and minresult ds.b 1 ; search result

org $1500clrastaa 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

loop ldab mincmpb maxlbhi notfoundaddb max ; compute meanlsrb ; “

stab mean ; save meanldaa b,x ; get a copy of the element arr[mean]cmpa #keybeq foundbhi search_loldaa meanincastaa min ; place mean+1 in min to continuebra loop

search_lo ldaa meandecastaa maxbra loop

found ldaa #1staa result

notfound swiarr db 1,3,6,9,11,20,30,45,48,60

db 61,63,64,65,67,69,72,74,76,79db 80,83,85,88,90,110,113,114,120,123end

Strings• A sequence of characters terminated by a NULL (ASCII code 0) or

other special character such as EOT (ASCII code 4).• 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.• 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.

• Example 4.4 Write a program to convert the unsigned 8-bit binary number in accumulator A into BCD digits terminated by a NULL character. Each digit is represented in ASCII code.

• Solution:– 4 bytes are needed to hold the converted BCD digits.– Repeated division by 10 method is used.

test_dat equ 34org $1000

buf ds.b 4 ; to hold the decimal stringtemp ds.b 2 ; "

org $1500ldab #test_datlds #$1500 ; initialize stack pointerldy #buftstbbne normalmovb #$30,bufclr buf+1 ; terminate the stringbra done

normal movb #0,1,-sp ; push a NULL into the stackclra

loop ldx #10idivaddb #$30 ; convert to ASCII codepshb ; push into stackcpx #0beq reversexgdx ; put quotient back to B

bra loopreverse tst 0,sp

beq donemovb 1,sp+,1,y+bra reverse

done swiend

• Example 4.5 Write a program to convert the 16-bit signed integer in D into a string of BCD digits.

• Solution– 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.– Up to 7 bytes are needed to hold the converted result.

test_dat equ -2478org $1000

buf ds.b 7 ; to hold the decimal stringorg $1500ldd #test_datlds #$1500 ; 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 ; "movb #$2D,1,y+ ; add minus sign and move pointer

normal movb #0,1,-sp ; push a NULL into the stackloop ldx #10

idivaddb #$30 ; convert to ASCII codepshb ; push into stack

cpx #0 ; is the quotient zero?beq reversexgdx ; put quotient back to Bbra loop

reverse tst 0,spbeq donemovb 1,sp+,1,y+ ; pop one byte and store it in bufferbra reverse

done swiend

Algorithm to convert from ASCII string that represents a BCD number to a binary number

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;

Example 4.6 Write a program to convert a BCD ASCII string to a binary number.Solution: minus equ $2D ; ASCII code of minus sign

org $1000in_buf fcc "9889" ; input ASCII to be converted

dc.b 0 ; null characterout_buf ds.b 2 ; holds the converted binary valuebuf2 ds.b 1 ; holds a zerobuf1 ds.b 1 ; holds the current digit value sign ds.b 1 ; holds the sign of the number error ds.b 1 ; indicates the occurrence of illegal character

org $1500clr signclr 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 1

inx ; move the pointercontinue 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

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 swiend

Character and Word Counting

• A string is terminated by the NULL character.• 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.

Sta

rt

char

_cnt

0

wor

d_cn

t 0

str_

ptr

add

r. o

f st

ring

curr

_cha

r [

str_

ptr]

str_

ptr

str

_ptr

+ 1

curr

_cha

r =

spa

ce, C

R,

LF

, or

tab?

wor

d_cn

t w

ord_

cnt

+ 1

curr

_cha

r [

str_

ptr]

str_

ptr

str

_ptr

+ 1

curr

_cha

r =

NU

LL

?

char

_cnt

c

har_

cnt

+ 1

curr

_cha

r =

NU

LL

?

char

_cnt

c

har_

cnt

+ 1

curr

_cha

r =

spa

ce, C

R,

LF

, or

tab?

Sto

p

Sto

p

Ski

p w

hite

spac

es

reac

h a

new

wor

d

skip

the

rem

aini

ngch

arac

ters

of

the

wor

d

Fig

ure

4.4

Log

ic f

low

for

cou

ntin

g ch

arac

ters

and

wor

ds i

n a

stri

ng

yes

yes

no

noyes

nono

yes

Example 4.7 Write a program to count the number of characters and words contained in a given string.Solution: tab equ $09sp equ $20cr equ $0Dlf equ $0A

org $1000char_cnt ds.b 1word_cnt ds.b 1string_x fcc "this is a strange test string to count chars and words."

dc.b 0org $1500ldx #string_xclr char_cntclr word_cnt

string_lp ldab 1,x+ ; get one character and move string pointerlbeq done ; is this the end of the string?inc char_cnt

; the following 8 instructions skip white space characters between wordscmpb #spbeq string_lpcmpb #tab

beq string_lpcmpb #crbeq string_lpcmpb #lfbeq string_lp

; a non-white character is the start of a new wordinc word_cnt

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

Start

Skip the white spaces to look forthe next word in the string

Is the current wordin the string equal to the word

to be searched?

Is this the end ofthe string?

Stop

yes

no

no

yes

Figure 4P.8 Flowchart of the word search program

Word Matching

Start

[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 wordto be compared

compare two words

skip theunmatched

word

Figure 4.5 Algorithm for searching a word from a string

tab equ $09 ; ASCII code of tab sp equ $20 ; ASCII code of space charactercr equ $0D ; ASCII code of carriage returnlf equ $0A ; ASCII code of line feedperiod equ $2E ; ASCII code of periodcomma equ $2C ; ASCII code of commasemicolon equ $3B ; ASCII code of semicolonexclamation equ $21 ; ASCII code of exclamationnull equ $0 ; ASCII code of NULL character

org $1000match ds.b 1

org $1500 clr match ldx #string_x

loop ldab 1,x+; the following 10 instructions skip white spaces to look for the next word in string_x

tstb beq done cmpb #sp beq loop cmpb #tab beq loop cmpb #cr

beq loopcmpb #lfbeq loop

; the first nonwhite character is the beginning of a new word to be comparedldy #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

; the following 10 instructions check to see if the end of the given word is reachedEndOfWd cmpa #null

bne next_wdcmpb #crbeq matchedcmpb #lfbeq matchedcmpb #tabbeq matchedcmpb #sp

beq matchedcmpb #periodbeq matchedcmpb #commabeq matchedcmpb #semicolonbeq matchedcmpb #exclamationbeq matched

; the following 11 instructions skip the remaining characters in the unmatched wordnext_wd ldab 1,x+

beq donecmpb #crlbeq loopcmpb #lflbeq loopcmpb #tablbeq loopcmpb #splbeq loopbra next_wd

matched ldab #1stab match

done swistring_x fcc "This string contains certain number of words to be matched."

dc.b 0word_x fcc "This"

dc.b 0end

String Insertion (1 of 2)

• The pointers to the string and the substring to be inserted are given.

• The insertion point is given.• The procedure is given in Figure 4.6.

insertion point

string

to be moved to the right

Step

1find out how many

characters need to be moved

count the # of characters to be inserted2

make room for the substring to be inserted3

4

insert the substring

Figure 4.6 Major steps of substring insertion

Example 4.9 Write a program to implement the string insertion algorithm.

String Insertion (2 of 2)

org $1000ch_moved ds.b 1 ; number of characters to be movedchar_cnt ds.b 1 ; number of characters of the substring to be insertedsub_strg fcc "the first and most famous "

dc.b 0string_x fcc "Yellowstone is national park."

dc.b 0offset equ 15ins_pos equ string_x+offset ; insertion point

org $1500; the next 7 instructions count the number of characters to be moved

ldaa #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

; the following 3 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 insertionldx #ins_pos ; set up pointers to prepare insertionldy #sub_strg ; "ldab char_cnt

insert_lp movb 1,y+,1,x+dbne b,insert_lpswiend

[<label>] bsr <rel> [<comment>] ; branch to subroutine[<label>] jsr <opr> [<comment>] ; jump to subroutine[<label>] rts [<comment>] ; return from subroutine[<label>] call <opr> [<comment>] ; to be used in expanded memory

rtc ; return from CALLwhere

<rel> is the offset to the subroutine<opr> is the address of the subroutine and is specified in the DIR, EXT, or INDexedaddressing mode.

Subroutines• A sequence of instructions that can be called from various places in

the program• Allows the same operation to be performed with different

parameters• Simplifies the design of a complex program by using the divide-and-

conquer approach• Instructions related subroutine calls

main program

subroutine 1 subroutine 2 subroutine 3

Subroutine1.1

Subroutine 1.2

Subroutine 1.2.1

Subroutine 2.1

Subroutine 2.1.1

Subroutine 3.1

Subroutine 3.1.1

Subroutine 3.2

Subroutine 3.2.1

Figure 4.7 A structured program

Program Structure

.

.

.<call> subroutine_x

.

.

.

.

.

.

.

.<return>

caller

subroutine_x

Figure4.8 Program flow during a subroutine call

Subroutine Processing

Issues in Subroutine Calls• Parameter passing

– Use registers– Use the stack– Use global memory

• Returning results– Use registers– Use the stack (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

Local variables

Saved registers

Return address

Incoming parameters

SP

Figure 4.9 Structure of the 68HC12 stack frame

Stack Frame (1 of 2)

• The region in the stack that holds incoming parameters, the subroutine return address, local variables, and saved registers is referred to as stack frame.

• The stack frame is also called activation record.

Example 4.10 Draw the stack frame for the following program segment after the leas –10,sp instruction is executed:

ldd #$1234pshdldx #$4000pshxjsr sub_xyz…

sub_xyz pshdpshxpshyleas -10,sp…

Solution: The stack frame is shown in Figure 4.10. $1234

$4000

return address

$1234

$4000

contents of y

10 bytes for localvariables

SP

Figure 4.10 Stack frame of example 4.10

Stack Frame (2 of 2)

Examples of Subroutines• Algorithm for finding the greatest common divisor of Integers m and n

– Step 1If m = n then gcd m;return;

– Step 2If n < m then swap m and n.

– Step 3gcd 1.If m = 1 or n = 1 then return.

– Step 4p = n % m;

– Step 5if (p == 0) then m is the gcd.else n m;m p;goto Step 4.

Example 4.11 Write a subroutine to compute the greatest common divisor of two 16-bit unsigned integers.

Solution: The two 16-bit incoming parameters are passed in index register X and double accumulator D. The stack frame of this subroutine is shown below.

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 equ 3575n equ 2925m_local equ 6 ; stack offset from SP for local variable mn_local equ 4 ; stack offset from SP for local variable norg $1000gcd ds.w 1 ; hold the gcd of m and n

org $1500lds #$1500 ; set up stack pointer ; set up stack pointerldd #m ; pass m in the stack ; push m in stackpshd ; “ldd #n ; pass n in the stack ; push n in stackpshd ; “jsr find_gcdstd gcdleas 4,sp ; deallocate space used by parametersswi

find_gcd pshxgcd_loop ldd n_local,sp ; compute p = n % m

ldx m_local,sp ; "idiv ; "cpd #0beq don

movw m_local,sp,n_local,sp ; n mstd m_local,sp ; m pbra gcd_loop

done ldd m_local,sp ; retrieve gcdpulx ; restore Xrtsend

Multi-Byte Division (1 of 2)

• The HCS12 provides instructions for performing 16-bit by 16-bit or 32-bit by 16-bit division

• The HCS12 does not have division instructions for larger numbers.

• Larger number divisions must be implemented by repeated subtraction method.

• The conceptual hardware for performing high precision division is shown in Figure 4.12.

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

Multi-Byte Division (2 of 2)

Example 4.12 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.13.

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

buf equ 0 ; distance of buf from the top of the stacki equ 4 ; distance of i from the top of the stackR equ 5 ; distance of R from the top of the stackQ equ 9 ; distance of Q from the top of the stackdivisor equ 21 ; distance of divisor from the top of the stackdividend equ 25 ; distance of dividend from the top of the stackquotient equ 29 ; distance of quotient from the top of the stackremainder equ 33 ; distance of remainder from the top of the stacklocal equ 13 ; number of bytes for local variablesdvdend_hi equ $42 ; dividend to be testeddvdend_lo equ $4c15 ; "dvsor_hi equ $0 ; divisor to be testeddvsor_lo equ $64 ; "

org $1000quo ds.b 4 ; memory locations to hold the quotientrem ds.b 4 ; memory locations to hold the remainder  org $1500 ; starting address of the program

lds #$1500 ; initialize stack pointerleas -8,sp ; make a hole of 8 bytes to hold the resultldd #dvdend_lopshdldd #dvdend_hipshd

ldd #dvsor_lopshdldd #dvsor_hipshdjsr div32 ; call the divide subroutineleas 8,sp

; the following 4 instructions get the quotient from the stackpuldstd quo

puldstd quo+2

; the following 4 instructions get the remainder from the stackpuldstd rempuldstd rem+2swi

div32 pshd ; 32-bit divide subroutinepshxpshyleas -local,spldd #0std R,sp ; initialize register R to 0std R+2,sp

ldd 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 rightrol 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 ; "

; the following 8 instructions subtract the divisor from register Rldd R+2,spsubd divisor+2,spstd buf+2,spldaa R+1,spsbca divisor+1,spstaa buf+1,spldaa R,spsbca divisor,spbcs smaller

; 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

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 remainder into the holeldd R,spstd remainder,spldd R+2,spstd remainder+2,sp

; the following 4 instructions copy the quotient into the holeldd Q,spstd quotient,sp

ldd Q+2,spstd quotient+2,spleas local,sp ; deallocate local variablespulypulxpuldrtsend

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

• Sorting is useful for improving the searching speed when an array or a file needs to be searched many times.

• Bubble sort is a simple, but inefficient sorting method.

• Example 2.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.

– Four bytes are needed for local variables.

Bubble Sort

Star

t

itera

tion

N -

1

in_o

rder

1

inne

rite

ratio

n

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

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 db 3,29,10,98,54,9,100,104,200,92,87,48,27,22,71

db 1,62,67,83,89,101,190,187,167,134,121,20,31,34,54org $1500lds #$1500 ; initialize stack pointerldx #array_xpshxldaa #npshajsr bubbleleas 3,sp ; deallocate space used by outgoing parametersswi ; break to D-Bug12 monitor

bubble pshdpshypshxleas -local,sp ; allocate space for local variablesldaa 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 ; "

cloop ldaa 0,x ; compare two adjacent elementscmpa 1,x ; "bls looptest

; 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 clooptst in_order,sp ; test array in_order flag after each iterationbne donedec iteration,spbne ploop

done leas local,sp ; deallocate local variablespulxpulypuldrtsend

i = 0

n - 1i =

n(n - 1)2

(4.1)

i = 0

n - 1(2i + 1) (4.2)n2 =

Finding the Square Root (1 of 2)

• 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

– 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.

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)

q_val

return address

[Y]

i_local

sum

SP

SP+2

SP+10

Figure 4.17 Stack frame of example 4.14

• 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 unsigned integer. 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.

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 $1000sq_root ds.b 2 ; to hold the square root of q

org $1500lds #$1500ldd #q_lopshdldd #q_hipshdjsr findSqRootstd sq_rootleas 4,spswi

findSqRootpshy ; save y in the stackleas -local,sp ; allocate local variablesldd #0 ; initialize local variable i to 0

std i_local,sp ; "std sum,sp ; initialize local variable sum to 0std sum+2,sp ; "

loop ldd i_local,spldy #2emul ; compute 2iaddd sum+2,sp ; add 2i to sumstd sum+2,sptfr y,dadcb sum+1,spstab sum+1,spadca sum,spstaa sum,sp

; 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 #0

staa sum+1,spldaa sum,spadca #0staa sum,spldd i_local,sp ; increment i by 1addd #1 ; “std i_local,sp

; 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 loopldd i_local,sp ; place sq_root in D before return

 ; deallocate space used by local variablesexit leas local,sp

pulyrtsend

Table 4.2 D-Bug12 monitor (version 4.x.x) routines

Subroutine Function pointer address

far main ( )getchar ( )putchar ( )printf ( )far GetCmdLine ( )far sscanhex ( )isxdigit ( )toupper ( )isalpha ( )strlen ( )strcpy ( )far out2hex ( )far out4hex ( )SetUserVector ( )far WriteEEByte( )far EraseEE ( )far ReadMem ( )far WriteMem ( )

Start of D-Bug12Get a character from SCI0 or SCI1Send a character out to SCI0 or SCI1Formatted string output-translates binary values to stringGet a line of input from the userConvert ASCII hex string to a binary integerCheck if a character (in B) is a hex digitConvert lower-case characters to upper-caseCheck if a character is alphabeticReturns the length of a NULL-terminated stringCopy a NULL-terminated stringOutput 8-bit number as 2 ASCII hex charactersOutput a 16-bit number as 4 ASCII hex charactersSetup a vector to a user's interrupt service routineWrite a byte to the on-chip EEPROM memoryBulk erase the on-chip EEPROM memoryRead data from the HCS12 memory mapWrite data to the HCS12 memory map

$EE80$EE84$EE86$EE88$EE8A$EE8E$EE92$EE94$EE96$EE98$EE9A$EE9C$EEA0$EEA4$EEA6$EEAA$EEAE$EEB2

Using the D-Bug12 Functionsto Perform I/O Operations (1 of 3)

int getchar (void)Pointer address: $EE84Returned value: 8-bit character in accumulator B

• All functions listed in Table 4.2 are written in C language.• The first parameter to the function is passed in accumulator D. The

remaining parameters are pushed onto the stack in the reverse order they are listed in the function declaration.

• Parameters of type char will occupy the lower order byte of a word pushed onto the stack.

• Parameters pushed onto the stack before the function is called remain on the stack when the function returns. It is the responsibility of the caller to remove passed parameters from the stack.

• All 8- and 16-bit values are returned in accumulator D. A returned value of type char is returned in accumulator B.

Using the D-Bug12 Functionsto Perform I/O Operations (2 of 3)

• Adding the following instruction sequence will read a character from SCI0 port:getchar equ $EE84

…jsr [getchar,PCR]

int putchar(int)Pointer address: $EE86Incoming parameter: character to be output in accumulator BReturned vale: the character that was sent (in B)- This function outputs a character to serial communication port SCI0.- The character to be output should be placed in accumulator B.- The following instruction sequence will output the character A to serial port SCI0 when

the program is running on the SSE256 or Dragon12 demo board.putchar equ $EE86

…ldab #$41 ; place the ASCII code of A in accumulator Bjsr [putchar,PCR]…

Using the D-Bug12 Functionsto Perform I/O Operations (3 of 3)

• int printf(char *format,…)– Pointer address: $EE88– Incoming parameters: zero or more integer data to be output on the stack, D contains the address of the format string. The format string must be terminated with a zero.– Returned value: number of characters printed in D.

• This function is used to convert, format, and print its argument as standard output 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:

1. ASCII characters which will be copied directly to the display device.2. Conversion specifications. Each conversion specification begins with

a percent sign (%).3. 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.

The Meaning of Optional Characters

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 %

Example for outputting a message (Flight simulation):CR equ $0DLF equ $0Aprintf equ $EE88

…ldd #promptjsr [printf,PCR]…

prompt db “Flight simulation”,CR,LF,0

Formatting Characters Supported by the printf() function:

Example for outputting three numbers m, n, and gcd along with a message:

CR equ $0DLF equ $0Aprintf equ $F686

…ldd gcdpshdldd npshdldd mpshdldd #promptjsr [printf,PCR]leas 6,sp…

prompt db “The greatest common divisor of %d and %d is %d”,CR,LF,0

• int far GetCmdLine(char *CmdLineStr, int CmdLineLen)– Pointer address: $EE8A– Incoming parameters: a pointer to the buffer where the input string is

to be stored and the maximum number of characters that will be accepted by this function.

• This function is used to obtain a line of input from the user.

• The reception of an ASCII carriage return ($0D) terminates the reception of characters from the user.

• The caller of this function normally would output a message so that the user knows to enter a message. The example in the next page illustrates this interaction.

printf equ $EE88GetCmdLine equ $EE8Acmdlinelen equ 100CR equ $0DLF equ $0A

…prompt db “Please enter a string: “,CR,LF,0

…inbuf ds.b 100

…ldd #prompt ; output a prompt to remind the user to jsr [printf,PCR] ; enter a stringldd #cmdlinelen ; push the CmdLineLen pshd ; “ldd #inbufcall [GetCmdLine,PCR] ; read a string from the keyboardpuld ; clean up the stack

• 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.

• Solution: The logic structure of the program is– Step 1

• Output the message “The prime numbers between 1000 and 2000 are as follows:”.

– Step 2• For every number between 100 and 1000

– call the test_prime() 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.

SP

num

return address

[X]

prime_flag

ilimit

iSP + 2

SP + 4

SP + 9

Figure 4.18 Stack frame for the prime test subroutine

• Step 1– Let num, i, and isprime represent

the number to be tested, the loop index, and the flag to indicate if num is prime.

• Step 2– isprime ¬ 0;

• Step 3– For i = 2 to num/2 do if num % i =

0 then return; isprime ¬ 1; return;– The Stack frame of the function

test_prime ():

The Algorithm of the test_prime()

CR equ $0DLF equ $0Ai equ 0 ; distance of variable i from stack topilimit equ 2 ; distance of variable ilimit from stack topprime_flag equ 4 ; distance of variable isprime from stack topnum equ 9 ; distance of variable num from the stack topplocal equ 5 ; number of bytes allocated to local variablesupper equ 2000 ; upper limit for testing primelower equ 1000 ; lower limit for testing primeprintf equ $EE88 ; location where the address of printf() is stored

org $1000out_buf ds.b 10prime_cnt ds.b 1k ds.b 2temp ds.b 2

org $1500ldx #upperstx temppshxldx #lowerstx k ; initialize k to 100 for prime testingpshx

ldd #format0jsr [printf,PCR]leas 4,spclr prime_cnt

again ldd kcpd #upperbhi stop ; stop when k is greater than upperpshdjsr prime_tst ; test if k is primeleas 2,sp ; deallocate space used by outgoing parameterststbbeq next_k ; test next integer if k is not primeinc prime_cnt ; increment the prime countldd kpshdldd #format1jsr [printf,PCR] ; output kleas 2,spldaa prime_cntcmpa #8 ; are there 8 prime numbers in the current line?blo next_k

; output a CR, LF if there are already 8 prime numbers in the current line

ldd #format2jsr [printf,PCR]clr prime_cntldx kinxstx kbra again

next_k ldx kinxstx kjmp again

stop swiprime_tst pshx

leas -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

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,spis_prime ldab prime_flag,sp ; put the result in B

leas plocal,sppulxrts

formmat0 db CR,LF,"The prime numbers between %d and %d are as follows: db ",CR,LF,CR,LF,0

format1 db " %d ",0format2 db " ",CR,LF,0

end

>g 1500The 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 NZVC30 1560 1500 07D1 15DE 07:D1 1001 0000xx:1560 34 PSHX >

Program Execution Result

Tips for Program Debugging 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.

General Debugging Strategy

• Make sure all leaf subroutines work correctly by using the methods described in Section 2.9.

• Debug intermediate subroutines. Make sure no intermediate subroutines get stuck.

• Debug the top level program.