Sunteți pe pagina 1din 42

Assembler Programming

Chapter 6
EEL-4746 Best
Practices
EEL-4746 Best Practices
1. All programs must begin with the following
comment
***************************
* EEL-4746 Spring 2004 Semester
* Homework #N Due (Due Date)
* Problem #M
* Name of Partner A
* Name of Partner B
****************************
* Description of Program
EEL-4746 Best Practices
2. All subroutines must begin with the
following comment
***************************
* Subroutine Name: Mysub
* Input parameter list:
* Output parameter list:
* Registers changed list:
****************************
* Description of Subroutine
EEL-4746 Best Practices
3. All lines must contain a comment
4. All labels must end with a semicolon
5. Must use a symbol for all constants

EEL-4746 Best Practices
5. Program must have the following format:
Header Comment
***********************
* Standard Symbols
Data EQU $0000
Program EQU $E000
Stack EQU $00FF
Reset EQU $FFFE
*******************
Place your symbols here
******************
* Program
Top: ORG Program
Label: Program line ; comment
**************************
* Data
ORG Data
Variable {Directive} ; Data goes here
ORG Reset
FDB Top

Additional Comments
To Indent or Not Indent
Not really used in assembly language programming
Upper,Lower, and Mixed Cases
Be consistent
Symbols for constants in ALLUPPERCASE
Labels for in-memory variables in lowercase
Code labels in MixedCase
Instructions all uppercase or all lowercase
Etc
Subroutine Headers
Develop the habit of placing comments before subroutines.
The comment should give the function of the subroutine, the
input values it expects, and the registers that it modifies.

Pseudo-code
A fictitious programming language
which allows a general algorithm for a
computer program to be developed.
Design process
1. Develop program using pseudo-code
2. Convert pseudo-code to 68HC11 assembly
language
Structured Assembly Language
Programming
If Then Else End IF
Pseudo-Code Syntax
If Variable_A Condition Variable_B Then
Pseudo Code for Then condition
Else (Optional)
Pseudo Code B for Else condition
End If


Structured Assembly Language
Programming
LDAA Variable_A
CMPA Variable_B
B?? Else ; Opposite of condition
Code for Then part
.
BRA END_IF ; need to skip else part
Else : Code for Else part
..
END_IF: Rest of Code


Structured Assembly Language
Programming
If-Then-Else-End IF
Condition : Branch to Use (Opposite of condition)
<> : BEQ (Branch if equal)
= : BNE (Branch if not equal)
Signed
<= : BGT (Branch if greater than)
< : BGE (Branch if greater than or equal)
>= : BLT (Branch if less than)
> : BLE (Branch if less than or equal)
Unsigned
<= : BHI (Branch if higher)
< : BHS (Branch if higher or same)
>= : BLO (Branch if lower)
> : BLS (Branch if lower or same)



If-Then-Else Example
Pseudo-code
IF temp > max_temp then
Then code
Else
Else code
End If
If-Then-Else Example
Assembly Language
LDAA Temp
CMPA MAX_TEMP
BLS Else
Then code here
BRA ENDIF
ELSE:
ELSE code here
EndIf:
Rest of program here
Structured Assembly Language
Programming
Loops
For Loops
While-Do Loop
Do-While or (Repeat Until) Loops

Structured Assembly Language
Programming
For Loops
Pseudo-code Syntax
For loop_index = start_index to end_index
Begin
Code to Execute
..
..
End For Loop


Structured Assembly Language
Programming
Assembly Language
Use one of the registers for the loop index.
A,B=8 bit (255 max)
X,Y=16 bit (65535 max)
Must use memory if index value is greater than 65535
Example Code Fragment
LDAA #start_index
Loop: Start of Code to Execute (must not change A)
.
INCA
CMPA #end_index
BLS Loop



Structured Assembly Language
Programming
What if you need the loop index register (e.g. A)
in your code?
Example Code Fragment
LDAA #start_index
Loop: Start of Code to Execute
PSHA ; Save A on stack
Use A
.
PULA ; Restore A from stack
INCA
CMPA #end_index
BLS Loop


Structured Assembly Language
Programming
For Loops (Count down)
Pseudo-code Syntax
For loop_index = end_index downto start_index
Begin
Code to Execute
..
..
End For Loop


Structured Assembly Language
Programming
Example Code Fragment
LDAA #end_index
Loop: Start of Code to Execute
.
DECA
CMPA #start_index
BHS Loop


Structured Assembly Language
Programming
For Loops (Count down from N to 1)
This counts N items
Pseudo-code Syntax
For loop_index = end_index downto 1
Begin
Code to Execute
..
..
End For Loop


Structured Assembly Language
Programming
Example Code Fragment
LDAA #N
Loop: Start of Code to Execute
.
DECA
BNE Loop ; Save one statement


TPS Quiz
Structured Assembly Language
Programming
While-Do Loops
Pseudo-code Syntax
While Variable Condition Constant_VALUE
Do Code Here
Begin
Code to Execute
..
..
End While


Structured Assembly Language
Programming
While-Do Loops
Loop: LDAA Variable
CMPA #Constant_Value
B?? End_While ; (opposite of condition)
Do code here

..
BRA Loop
End_While: ; End of While loop



Structured Assembly Language
Programming
While-Do
Condition : Branch to Use (Opposite of condition)
<> : BEQ (Branch if equal)
= : BNE (Branch if not equal)
Signed
<= : BGT (Branch if greater than)
< : BGE (Branch if greater than or equal)
>= : BLT (Branch if less than)
> : BLE (Branch if less than or equal)
Unsigned
<= : BHI (Branch if higher)
< : BHS (Branch if higher or same)
>= : BLO (Branch if lower)
> : BLS (Branch if lower or same)



Structured Assembly Language
Programming
Example: Temp > #$4F (unsigned)
Pseudo-code:
While Temp > $4F
Do
(Execute your code here)
End_While: ; End of While loop



Structured Assembly Language
Programming
While Temp > #$4F (unsigned)
Assembly Code
Loop: LDAA Temp
CMPA #$4F
BLS End_While ; (opposite of >)
Do code here

..
BRA Loop
End_While: ; End of While loop
Structured Assembly Language
Programming
Do-While or (Repeat-Until) Loops
Pseudo-code Syntax
Do (or Repeat)
Begin
Code to Execute
..
..
While Condition (or Until Condition)


Structured Assembly Language
Programming
Do-While or (Repeat-Until) Loops
Assembly Language Syntax
Loop:
Do Code Here
..
..
LDAA Variable
CMPA #Constant
B?? Loop ; (same as condition)


Structured Assembly Language
Programming
Do-While or (Repeat Until)
Condition : Branch to Use (Same as condition)
= : BEQ (Branch if equal)
<> : BNE (Branch if not equal)
Signed
> : BGT (Branch if greater than)
>= : BGE (Branch if greater than or equal)
< : BLT (Branch if less than)
<= : BLE (Branch if less than or equal)
Unsigned
> : BHI (Branch if higher)
>= : BHS (Branch if higher or same)
< : BLO (Branch if lower)
<= : BLS (Branch if lower or same)
Example
Write a 68HC11 assembly language
program that converts X into an
equivalent ASCII signed decimal value.
Store your result in a memory location
labeled: Result.
Pseudo-code
X = Number_to_convert
sign = +
if X < 0 then
sign = -
X = -X
end If
result[0] = sign
call X2ASC(X)
end program
X2ASC is a subroutine that converts the X register
(unsigned) to ASCII
Well put this code into
a subroutine called
SX2ASC that converts
the X register (signed)
to ASCII.
Lets convert the code
For this line of pseudo-code:
X = Number_to_convert
Well create the following code
NUMBER: EQU $8001 ; -32767

ORG CODE_AREA
Main: LDX #NUMBER ;Put it in regX
JSR SX2ASC ;Signed convert
End: BRA End ;Infinite loop
Next line
At the start of the SX2ASC subroutine, we have the
pseudocode line:
sign = +
Well convert this to:
ORG DATA_AREA

sign: RMB 1 ;1 byte for sign char

ORG CODE_AREA

SX2ASC: LDAA #+ ; Take an ASCII + sign.
STAA sign ; Store it in sign var.
Next line
Next, we have:
if X < 0 then
end if
This converts to the assembly:
CPX #0 ; Compare X to 0.
BHS endIf ; If X>=0, skip if body
(IF body goes here)
endIf: (code after IF goes here)
A more difficult case
Consider the pseudocode line:
X = X (X gets negative X)
Problem: Theres no NEGX instruction!
How can we work around this?
One solution:
varX RMB 2 ; Reserve space for X in mem.

STX varX ; Save X in memory at varX
LDD #0 ; Load accum. D with a 0
SUBD varX ; Let D = 0 varX = -X
XGDX ; Copy D back to X.
Full SX2ASC in assembly
SX2ASC: LDAA #'+ ; Take an ASCII "+" sign.
STAA sign ; Store it in "sign" variable.
CPX #0 ; Compare X to 0.
BHS endIf ; If X < 0, then...
LDAA #'- ; Take an ASCII "-" sign.
STAA sign ; Store it in "sign" variable.
STX varX ; Save X in "varX" variable.
LDD #0 ; D = 0.
SUBD varX ; D = 0 - varX = -varX = -X.
XGDX ; Copy D back to X.
endIf: LDAA sign ; A = sign character.
STAA result+0 ; Store sign char. in result[0].
JSR X2ASC ; Conv. unsigned X to result[1-5].
RTS ; End of subroutine; return.
X

=

X

Pseudo-code: X2ASC (w. divide)
function X2ASC(X,result)
D = X
for B = 0 to 3
A = floor(D / convert[B])
; where convert[]= 10000,1000,100,10
D = D A*convert[B] ; Let D be the remainder
A = A or #$30 ; Convert A from 0-9 to ASCII
result[B+1] = A
end for
A = D ; D should have the ones
A = A or #$30 ; Convert to ASCII
result[4] = A
end function
Note: When converting this to working assembly
code, we must be careful about overlapping
registers.
for loop outline
The skeleton of our for loop:
for B = 0 to 3
(body of for loop)
end for
Translates to:
LDAB #0
forBody: ;body code goes here
INCB ; B = B + 1
CMPB #3 ; Compare B to 3
BLS forBody ; If B<=3, continue
But, we must be careful to preserve the value of
B within the body code!
Accessing an array of words
We can set up the convert[] array as follows:
convert FDB 10000,1000,100,10
But, how do we access convert[B]?
CLRA ; Effectively sets D=B
ASLD ; Double D, its 2B.
XGDY ; Transfer this to Y
LDX convert,Y ; X = *(convert+2B)
But, this only works if convert array is on page 0!
More generally, wed have to do this after the ASLD:
ADDD #convert ; D = convert+2B
XGDY ; Transfer D to Y
LDX 0,Y ; X = *Y = convert[B]
Unsigned X2ASC in assembly
X2ASC: STX varD ; Initialize variable D = X.
LDAB #0 ; For B = 0 to 3,
ForBody:STAB varB ; Save variable B.
CLRA ; Clear MSB of accumulator D.
ASLD ; Double D to get 2*varB.
XGDY ; Move it into Y.
LDX convert,Y ; Let X = *(convert+Y) = convert[varB]
LDD varD ; Load old variable D.
IDIV ; (X,D) = (quotient,remainder) of D/X.
STX quot ; Save quotient temporarily.
STD varD ; Save remainder as new variable D.
CLRA ; Clear MSB of accumulator D.
LDAB varB ; Set LSB of D = variable B.
XGDY ; Move value of B from D into Y.
INY ; Increment Y to be varB+1.
LDAA quot+1 ; A = LSB of quotient.
ORAA #$30 ; Convert A to ASCII.
STAA result,Y ; result[varB+1] = A.
LDAB varB ; Load old value of variable B.
INCB ; Increment B to next value.
CMPB #3 ; Compare B with 3.
BLS ForBody ; End For. (Continue while B <= 3.)
LDAA varD+1 ; A = LSB of D (final remainder).
ORAA #$30 ; Convert A to ASCII.
STAA result+5 ; result[5] = A.
RTS ; Subroutine done; return.
X
=
c
o
n
v
e
r
t
[
B
]

r
e
s
u
l
t
[
B
+
1
]
=
A
+
$
3
0

Pseudo-code: X2ASC (w/o divide)
Function X2ASC(X,Result)
D = X
For B = 0 to 3
A = 0
; Count the number of times Convert can be subtracted from D
While D>0 Do
A = A + 1
D = D Convert[B] ; Convert= 10000,1000,100,10
End While

D
=
D + Convert[B]
A = A 1
A = A OR #$30 ; Convert A from 0-9 to ASCII
Result[B] = A
END For
A = D ; D should have the ones
A = A OR #$30 ; Convert to ASCII
Result[4] = A
End Function Note: When converting this to HC11 assembly
code, we must be careful because the HC11s
register D overlaps registers A and B.
This version avoids doing division
and would work on a processor
without a divide instruction.

S-ar putea să vă placă și