• No results found

Chapter 4

N/A
N/A
Protected

Academic year: 2020

Share "Chapter 4"

Copied!
81
0
0

Loading.... (view fulltext now)

Full text

(1)

Chapter 4

(2)

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

(3)

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

Mnemonic psha pshb pshc pshd pshx pshy pula pulb pulc puld pulx puly Function

push A into the stack push B into the stack push CCR into the stack push D into stack

push X into the stack push Y into the stack pull A from the stack pull B from the stack pull CCR from the stack pull D from the stack pull X from the stack pull Y from the stack

Equivalent instruction staa 1, -SP

stab 1, -SP none

std 2, -SP stx 2, -SP sty 2, -SP ldaa 1, SP+ ldab 1, SP+ none

ldd 2, SP+ ldx 2, SP+ ldy 2, SP+

HCS12 Support for the Stack Data Structure

• A 16-bit stack pointer (SP)

(4)

-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

(5)

Start

i = 0 result = -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

(6)

N equ 30 ; array count

notfound equ -1

key equ 190 ; define the searching key

org $1000

result rmw 1 ; reserve a word for result

org $1500 ; starting point of the program

ldy #N ; set up loop count

ldd #notfound

std result ; initialize the search result

ldd #key

ldx #vec_x ; place the starting address of vec_x in X

loop cpd 2,X+ ; compare the key with array element & move pointer

beq found

dbne Y,loop ; have we gone through the whole array?

bra done

found dex ; need to restore the value of X to point to the

dex ; matched element

stx result

done swi

vec_x dw 13,15,320,980,42,86,130,319,430,4, 90,20,18,55,30,51,37

(7)

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

(8)

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 count

key equ 69 ; key to be searched

org $1000

max ds.b 1 ; maximum index value for comparison

min ds.b 1 ; minimum index value for comparison

mean ds.b 1 ; the average of max and min

result ds.b 1 ; search result

org $1500

clra

staa min ; initialize min to 0

staa result ; initialize result to 0

ldaa #n-1

staa max ; initialize max to n-1

ldx #arr ; use X as the pointer to the array

loop ldab min

cmpb max lbhi notfound

addb max ; compute mean

(9)

stab mean ; save mean

ldaa b,x ; get a copy of the element arr[mean]

cmpa #key

beq found

bhi search_lo

ldaa mean

inca

staa min ; place mean+1 in min to continue

bra loop

search_lo ldaa mean

deca

staa max

bra loop

found ldaa #1

staa result

notfound swi

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

db 61,63,64,65,67,69,72,74,76,79

(10)

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:

(11)

test_dat equ 34 org $1000

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

org $1500 ldab #test_dat

lds #$1500 ; initialize stack pointer ldy #buf

tstb

bne normal movb #$30,buf

clr buf+1 ; terminate the string bra done

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

loop ldx #10

idiv

addb #$30 ; convert to ASCII code pshb ; push into stack

cpx #0 beq reverse

(12)

bra loop reverse tst 0,sp

beq done

movb 1,sp+,1,y+ bra reverse done swi

(13)

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.

(14)

test_dat equ -2478 org $1000

buf ds.b 7 ; to hold the decimal string org $1500

ldd #test_dat

lds #$1500 ; initialize stack pointer ldy #buf

cpd #0

bmi negate ; branch if the value is negative bne normal ; branch if the value is positive movb #$30,buf

clr buf+1 ; terminate the string bra done

negate coma ; when negative, complement the number comb ; "

addd #1 ; "

movb #$2D,1,y+ ; add minus sign and move pointer normal movb #0,1,-sp ; push a NULL into the stack

loop ldx #10

idiv

(15)

cpx #0 ; is the quotient zero? beq reverse

xgdx ; put quotient back to B bra loop

reverse tst 0,sp beq done

movb 1,sp+,1,y+ ; pop one byte and store it in buffer bra reverse

(16)

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

Step 1

sign  0

error  0

number  0

Step 2

If the character pointed to by in_ptr is the minus sign, then

sign  1

in_ptr  in_ptr + 1

Step 3

If 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 4

If sign = 1 and error = 0 ,then

number  two’s complement of number;

else

(17)

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 $1000

in_buf fcc "9889" ; input ASCII to be converted

dc.b 0 ; null character

out_buf ds.b 2 ; holds the converted binary value

buf2 ds.b 1 ; holds a zero

buf1 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 $1500

clr sign

clr error

clr out_buf

clr out_buf+1

clr buf2

ldx #in_buf

ldaa 0,x

cmpa #minus ; is the first character a minus sign?

bne continue ; branch if not minus

(18)

inx ; move the pointer

continue ldaa 1,x+ ; is the current character a NULL character? lbeq done ; yes, we reach the end of the string

cmpa #$30 ; is the character not between 0 to 9? lblo in_error ; "

cmpa #$39 ; "

lbhi in_error ; "

suba #$30 ; convert to the BCD digit value

staa buf1 ; save the digit temporarily

ldd out_buf

ldy #10

emul ; perform 16-bit by 16-bit multiplication

addd buf2 ; add the current digit value

std out_buf ; Y holds 0 and should be ignored

bra continue

in_error ldaa #1

staa error

done ldaa sign ; check to see if the original number is negative

beq positive

ldaa out_buf ; if negative, compute its two’s complement

ldab out_buf+1 ; “

coma ; “

(19)

addd #1 ; “

std out_buf

(20)

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

(21)
(22)

Example 4.7 Write a program to count the number of characters and words contained in a given string.

Solution:

tab equ $09

sp equ $20

cr equ $0D

lf equ $0A

org $1000

char_cnt ds.b 1

word_cnt ds.b 1

string_x fcc "this is a strange test string to count chars and words."

dc.b 0

org $1500

ldx #string_x

clr char_cnt

clr word_cnt

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 words

cmpb #sp

beq string_lp

(23)

beq string_lp

cmpb #cr

beq string_lp

cmpb #lf

beq string_lp

; a non-white character is the start of a new word

inc word_cnt

wd_loop ldab 1,x+ ; get one character and move pointer

beq done

inc char_cnt

; the following 8 instructions check the end of a word

cmpb #sp

lbeq string_lp

cmpb #tab

lbeq string_lp

cmpb #cr

lbeq string_lp

cmpb #lf

lbeq string_lp

bra wd_loop

done swi

(24)

Start

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

Is the current word in the string equal to the word

to be searched?

Is this the end of the string?

Stop

yes

no

no

yes

Figure 4P.8 Flowchart of the word search program

(25)

Start

[str_ptr] = NULL? str_ptr  string_x

match_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 + 1

str_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

(26)

tab equ $09 ; ASCII code of tab

sp equ $20 ; ASCII code of space character

cr equ $0D ; ASCII code of carriage return

lf equ $0A ; ASCII code of line feed

period equ $2E ; ASCII code of period

comma equ $2C ; ASCII code of comma

semicolon equ $3B ; ASCII code of semicolon

exclamation equ $21 ; ASCII code of exclamation

null equ $0 ; ASCII code of NULL character

org $1000

match 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

(27)

beq loop

cmpb #lf

beq loop

; the first nonwhite character is the beginning of a new word to be compared

ldy #word_x

ldaa 1,y+

next_ch cba

bne EndOfWd

cmpa #null ; check to see if the end of word is reached

beq matched ; "

ldaa 1,y+ ; get the next character from the word

ldab 1,x+ ; get the next character from the string

bra next_ch

; the following 10 instructions check to see if the end of the given word is reached

EndOfWd cmpa #null

bne next_wd

cmpb #cr

beq matched

cmpb #lf

beq matched

cmpb #tab

beq matched

(28)

beq matched

cmpb #period

beq matched

cmpb #comma

beq matched

cmpb #semicolon

beq matched

cmpb #exclamation

beq matched

; the following 11 instructions skip the remaining characters in the unmatched word

next_wd ldab 1,x+

beq done

cmpb #cr

lbeq loop

cmpb #lf

lbeq loop

cmpb #tab

lbeq loop

cmpb #sp

lbeq loop

bra next_wd

matched ldab #1

(29)

done swi

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

dc.b 0

word_x fcc "This"

dc.b 0

(30)

String Insertion

(1 of 2)

• The pointers to the string and the substring to be

inserted are given.

• The insertion point is given.

(31)

insertion point

string

to be moved to the right Step

1 find out how many

characters need to be moved

count the # of characters to be inserted 2

make room for the substring to be inserted 3

4

insert the substring

Figure 4.6 Major steps of substring insertion

Example 4.9

Write a program to implement the string

insertion algorithm.

(32)

org $1000

ch_moved ds.b 1 ; number of characters to be moved

char_cnt ds.b 1 ; number of characters of the substring to be

inserted

sub_strg fcc "the first and most famous "

dc.b 0

string_x fcc "Yellowstone is national park."

dc.b 0

offset equ 15

ins_pos equ string_x+offset ; insertion point

org $1500

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

ldaa #1

staa ch_moved

ldx #ins_pos ; x points to the insertion point

cnt_moved ldaa 1,x+

beq cnt_chars

inc ch_moved

bra cnt_moved

cnt_chars dex ; subtract 1 from x so it points to the NULL character

ldy #sub_strg ; y points to the substring

clr char_cnt

; the following 3 instructions count the move distance

(33)

beq mov_loop

inc char_cnt

bra char_loop

mov_loop tfr x,y ; make a copy of x in y

ldab char_cnt

aby ; compute the copy destination

ldab 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 insertion ldy #sub_strg ; "

ldab char_cnt

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

(34)

[<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 CALL

where

<rel> is the offset to the subroutine

<opr> is the address of the subroutine and is specified in the DIR, EXT, or INDexed addressing 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

(35)

main program

subroutine 1 subroutine 2 subroutine 3

Subroutine 1.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

(36)

. . .

<call> subroutine_x

. . . . . . . .

<return> caller

subroutine_x

Figure4.8 Program flow during a subroutine call

(37)

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

;

(38)

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.

(39)

Example 4.10

Draw the stack frame for the following program segment

after the

leas –10,sp

instruction is executed:

ldd #$1234

pshd

ldx #$4000

pshx

jsr sub_xyz

sub_xyz pshd

pshx pshy

leas -10,sp

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

$4000 return address

$1234 $4000 contents of y 10 bytes for local

variables

SP

Figure 4.10 Stack frame of example 4.10

(40)

Examples of Subroutines

Algorithm

for

finding the greatest common divisor of Integers

m

and

n

Step 1

If m = n then

gcd  m;

return;

Step 2

If n < m then swap m and n.

Step 3

gcd  1.

If m = 1 or n = 1 then return.

Step 4

p = n % m;

Step 5

if (p == 0) then m is the gcd. else

n  m;

m  p;

(41)

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

SP 2 bytes

2 bytes 2 bytes 2 bytes

(42)

m equ 3575

n equ 2925

m_local equ 6 ; stack offset from SP for local variable m

n_local equ 4 ; stack offset from SP for local variable n

org $1000

gcd ds.w 1 ; hold the gcd of m and n

org $1500

lds #$1500 ; set up stack pointer ; set up stack pointer

ldd #m ; pass m in the stack ; push m in stack

pshd ; “

ldd #n ; pass n in the stack ; push n in stack

pshd ; “

jsr find_gcd

std gcd

leas 4,sp ; deallocate space used by parameters

swi find_gcd pshx

gcd_loop ldd n_local,sp ; compute p = n % m

ldx m_local,sp ; "

idiv ; "

cpd #0

(43)

movw m_local,sp,n_local,sp ; n  m

std m_local,sp ; m  p

bra gcd_loop

done ldd m_local,sp ; retrieve gcd

pulx ; restore X

(44)

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.

(45)

ALU

P register

R register Q register

set lsb shift left

write R

32-bit

32-bit 32-bit C

Controller

msb lsb

Figure 4.12 Conceptual hardware for implementing repeated subtraction method

(46)

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+5 SP+

9

SP+21 SP+25 SP+29 SP+33

(47)

buf equ 0 ; distance of buf from the top of the stack

i equ 4 ; distance of i from the top of the stack

R equ 5 ; distance of R from the top of the stack

Q equ 9 ; distance of Q from the top of the stack

divisor equ 21 ; distance of divisor from the top of the stack

dividend equ 25 ; distance of dividend from the top of the stack

quotient equ 29 ; distance of quotient from the top of the stack

remainder equ 33 ; distance of remainder from the top of the stack

local equ 13 ; number of bytes for local variables

dvdend_hi equ $42 ; dividend to be tested

dvdend_lo equ $4c15 ; "

dvsor_hi equ $0 ; divisor to be tested

dvsor_lo equ $64 ; "

org $1000

quo ds.b 4 ; memory locations to hold the quotient

rem ds.b 4 ; memory locations to hold the remainder

org $1500 ; starting address of the program

lds #$1500 ; initialize stack pointer

leas -8,sp ; make a hole of 8 bytes to hold the result

ldd #dvdend_lo

pshd

ldd #dvdend_hi

(48)

ldd #dvsor_lo pshd

ldd #dvsor_hi

pshd

jsr div32 ; call the divide subroutine

leas 8,sp

; the following 4 instructions get the quotient from the stack puld

std quo

puld

std quo+2

; the following 4 instructions get the remainder from the stack puld

std rem

puld

std rem+2

swi

div32 pshd ; 32-bit divide subroutine

pshx pshy

leas -local,sp

ldd #0

std R,sp ; initialize register R to 0

(49)

ldd dividend,sp

std Q,sp ; place dividend in register Q

ldd dividend+2,sp

std Q+2,sp

ldaa #32

staa i,sp ; initialize loop count

loop lsl Q+3,sp ; shift register pair Q and R to the right

rol Q+2,sp ; by 1 bit

rol 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 R

ldd R+2,sp

subd divisor+2,sp

std buf+2,sp

ldaa R+1,sp

sbca divisor+1,sp

staa buf+1,sp

ldaa R,sp

sbca divisor,sp

(50)

; the following 6 instructions store the difference back to R register

staa R,sp

ldaa buf+1,sp

staa R+1,sp

ldd buf+2,sp

std R+2,sp

ldaa Q+3,sp

oraa #01 ; set the least significant bit of Q register to 1

staa Q+3,sp

bra looptest

smaller ldaa Q+3,sp

anda #$FE ; set the least significant bit of Q register to 0

staa Q+3,sp

looptest dec i,sp

lbne loop

; the following 4 instructions copy the remainder into the hole

ldd R,sp

std remainder,sp

ldd R+2,sp

std remainder+2,sp

; the following 4 instructions copy the quotient into the hole

ldd Q,sp

(51)

ldd Q+2,sp

std quotient+2,sp

leas local,sp ; deallocate local variables puly

(52)

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.

(53)

St ar t it er at io n N 1 in _o rd er 1 in ne r it er at io n ye s sw ap a rr ay [i ] & a rr ay [i + 1] ar ra y[ i] > a rr ay [i + 1] ? in _o rd er 0 in ne r in ne r - 1 in ne r = 0 ? i 0 i i +

1 yes

(54)

arr equ 13 ; distance of the variable arr from stack top

arcnt equ 12 ; distance of the variable arcnt from stack top

buf equ 3 ; distance of local variable buf from stack top

in_order equ 2 ; distance of local variable in_order from stack top

inner equ 1 ; distance of local variable inner from stack top

iteration equ 0 ; distance of local variable iteration from stack top

true equ 1

false equ 0

n equ 30 ; array count

local equ 4 ; number of bytes used by local variables

org $1000

array_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,54

org $1500

lds #$1500 ; initialize stack pointer

ldx #array_x

pshx

ldaa #n

psha

jsr bubble

leas 3,sp ; deallocate space used by outgoing parameters

(55)

bubble pshd pshy pshx

leas -local,sp ; allocate space for local variables

ldaa arcnt,sp ; compute the number of iterations to be performed

deca ; "

staa iteration,sp ; "

ploop ldaa #true ; set array in_order flag to true before any iteration

staa in_order,sp ; "

ldx arr,sp ; use index register X as the array pointer ldaa iteration,sp ; initialize inner loop count for each iteration

staa inner,sp ; "

cloop ldaa 0,x ; compare two adjacent elements

cmpa 1,x ; "

bls looptest

; the following five instructions swap the two adjacent elements

staa buf,sp ; swap two adjacent elements

ldaa 1,x ; "

staa 0,x ; "

ldaa buf,sp ; "

staa 1,x ; "

ldaa #false ; reset the in-order flag

(56)

looptest inx

dec inner,sp

bne cloop

tst in_order,sp ; test array in_order flag after each iteration

bne done

dec iteration,sp

bne ploop

done leas local,sp ; deallocate local variables

(57)

i = 0 n - 1

i = 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

(58)

Start

i  0 sum  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

(59)

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

(60)

q_hi equ $000F ; upper word of q

q_lo equ $4240 ; lower word of q

i_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 $1000

sq_root ds.b 2 ; to hold the square root of q

org $1500

lds #$1500

ldd #q_lo

pshd

ldd #q_hi

pshd

jsr findSqRoot

std sq_root

leas 4,sp

swi findSqRoot

pshy ; save y in the stack

leas -local,sp ; allocate local variables

(61)

std i_local,sp ; "

std sum,sp ; initialize local variable sum to 0

std sum+2,sp ; "

loop ldd i_local,sp

ldy #2

emul ; compute 2i

addd sum+2,sp ; add 2i to sum

std sum+2,sp

tfr y,d

adcb sum+1,sp

stab sum+1,sp

adca sum,sp

staa sum,sp

; add 1 to sum (need to propagate carry to the most significant byte of sum)

ldaa #1

adda sum+3,sp

staa sum+3,sp

ldaa sum+2,sp

adca #0

staa sum+2,sp

ldaa sum+1,sp

(62)

staa sum+1,sp

ldaa sum,sp

adca #0

staa sum,sp

ldd i_local,sp ; increment i by 1

addd #1 ; “

std i_local,sp

; compare sum to q_val by performing subtraction (need consider borrow)

ldd sum+2,sp

subd q_val+2,sp

ldaa sum+1,sp

sbca q_val+1,sp

ldaa sum,sp

sbca q_val,sp

lblo loop

ldd i_local,sp ; place sq_root in D before return ; deallocate space used by local variables

exit leas local,sp

(63)

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

Get a character from SCI0 or SCI1 Send a character out to SCI0 or SCI1

Formatted string output-translates binary values to string Get a line of input from the user

Convert ASCII hex string to a binary integer Check if a character (in B) is a hex digit Convert lower-case characters to upper-case Check if a character is alphabetic

Returns the length of a NULL-terminated string Copy a NULL-terminated string

Output 8-bit number as 2 ASCII hex characters Output a 16-bit number as 4 ASCII hex characters Setup a vector to a user's interrupt service routine Write a byte to the on-chip EEPROM memory Bulk erase the on-chip EEPROM memory Read data from the HCS12 memory map Write 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 Functions

(64)

int getchar (void)

Pointer address: $EE84

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

(65)

• Adding the following instruction sequence will read a character

from SCI0 port:

getchar equ $EE84

jsr [getchar,PCR]

int putchar(int)

Pointer address: $EE86

Incoming parameter: character to be output in accumulator B Returned 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 B

jsr [putchar,PCR]

(66)

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:

(67)

Table 4.3 Optional formatting characters

Character Description

-(minus sign) FieldWidth

. (period) Precision

h

l(letter ell)

Left justifies the converted argument.

Integer number that specifies the minimum field width for the converted arguemnt. 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 to display 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.

(68)

Table 4.4 Printf() conversion characters d, i

o x X u c s p %

character Argument type; displayed as int; signed decimal number

int; unsigned octal number (without a leading zero) int; unsigned hex number using abcdef for 10...15 int; unsigned hex number using ABCDEF for 10...15 int; unsigned decimal number

int; single character

char *; 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 $0D

LF equ $0A

printf equ $EE88

ldd #prompt

jsr [printf,PCR]

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

(69)

Example

for outputting three numbers

m, n,

and

gcd

along

with a message:

CR equ $0D

LF equ $0A

printf equ $F686

ldd gcd

pshd

ldd n

pshd

ldd m

pshd

ldd #prompt

jsr [printf,PCR]

leas 6,sp

(70)

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.

(71)

printf equ $EE88

GetCmdLine equ $EE8A

cmdlinelen equ 100

CR equ $0D

LF 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 string

ldd #cmdlinelen ; push the CmdLineLen

pshd ; “

ldd #inbuf

call [GetCmdLine,PCR] ; read a string from the keyboard

(72)

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.

(73)

S P

num return address

[X] prime_flag

ilimit i SP + 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 ():

(74)

CR equ $0D

LF equ $0A

i equ 0 ; distance of variable i from stack top

ilimit equ 2 ; distance of variable ilimit from stack top

prime_flag equ 4 ; distance of variable isprime from stack top

num equ 9 ; distance of variable num from the stack top

plocal equ 5 ; number of bytes allocated to local variables

upper equ 2000 ; upper limit for testing prime

lower equ 1000 ; lower limit for testing prime

printf equ $EE88 ; location where the address of printf() is stored

org $1000

out_buf ds.b 10

prime_cnt ds.b 1

k ds.b 2

temp ds.b 2

org $1500

ldx #upper

stx temp

pshx

ldx #lower

stx k ; initialize k to 100 for prime testing

(75)

ldd #format0

jsr [printf,PCR]

leas 4,sp

clr prime_cnt

again ldd k

cpd #upper

bhi stop ; stop when k is greater than upper

pshd

jsr prime_tst ; test if k is prime

leas 2,sp ; deallocate space used by outgoing parameters

tstb

beq next_k ; test next integer if k is not prime

inc prime_cnt ; increment the prime count

ldd k

pshd

ldd #format1

jsr [printf,PCR] ; output k

leas 2,sp

ldaa prime_cnt

cmpa #8 ; are there 8 prime numbers in the current line?

blo next_k

(76)

ldd #format2

jsr [printf,PCR]

clr prime_cnt

ldx k

inx

stx k

bra again

next_k ldx k

inx

stx k

jmp again

stop swi

prime_tst pshx

leas -plocal,sp ; allocate local variable

ldaa #1

staa prime_flag,sp; set the flag to true

ldd num,sp

cpd #1

beq not_prime ; 1 is not a prime number

cpd #2

beq is_prime ; 2 is a prime number

lsrd ; compute num/2 as the test limit

(77)

ldd #2

std i,sp ; set first test number to 2

test_loop ldx i,sp

ldd num,sp

idiv

cpd #0 ; if num can be divided by i, then

beq not_prime ; it is not a prime

ldd i,sp

cpd ilimit,sp

beq is_prime ; num is prime at the end of test loop

ldx i,sp

inx

stx i,sp

bra test_loop

not_prime clr prime_flag,sp

is_prime ldab prime_flag,sp ; put the result in B leas plocal,sp

pulx

(78)

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

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

(79)

>g 1500

The 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 Encountered PP PC SP X Y D = A:B CCR = SXHI NZVC

30 1560 1500 07D1 15DE 07:D1 1001 0000 xx:1560 34 PSHX

>

(80)

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.

(81)

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.

Figure

Figure 4.1 Diagram of the HCS12 stack
Table 4.1 HCS12 push and pull instructions and their               equivalent load and store instructions
Figure 4.3 Flowchart for sequential searchyes
Figure 4P.8 Flowchart of the word search program
+7

References

Related documents

The purpose of this study was to evaluate the diagnostic utility of real-time elastography (RTE) in differentiat- ing between reactive and metastatic cervical lymph nodes (LN)

Following the positive outcome of the five trials proving the efficacy of endovascular treatment (EVT) in patients with anterior circulation acute ischemic stroke due to large

[r]

They also include certain information technology providers, health information organizations, most entities that provide data or document transmission and storage services

Pola arus musiman dan aliran sungai dari daratan Pulau Bangka, Pulau Sumatera di bagian barat serta aliran sungai dari Sungai Kapuas (dari daratan Kalimantan) di

Online game-based formative assessment tools: Quizlet, Quizizz, and Kahoot Some ideas on Assessment on the Virtual Environment?. Final Thoughts on Assessment on the

An analysis of the economic contribution of the software industry examined the effect of software activity on the Lebanese economy by measuring it in terms of output and value

In this paper, a simple empirical model that relates monthly clearness index and monthly direct normal fraction is used to estimate monthly and annual long-term DNI from