„Amiga Machine Language (Chapter 4)” változatai közötti eltérés
Innen: amigaspirit.hu - pegasos.hu Wiki
Ugrás a navigációhozUgrás a kereséshez
(initial import as separate page) |
(Nincs különbség)
|
A lap jelenlegi, 2009. május 25., 13:27-kori változata
Chapter 4.
---------
4.Our First Programs.
--------------------
You`re getting pretty far along in your knowledge of machine
language programming.In fact,you`re to the point where you can
write programs,and not just programs for demonstration purposes,
but ones that serve a real function.We`re assuming that you have
the AssemPro assembler and have loaded it.
If you`re using a different assembler,a few things must be done
differently.We covered those differences already in the chapter on
the different assemblers.
We`ve written the example programs as subroutines so they can be
tried out directly and used later.After assembling the program,you
can put the desired values in the register.Then you can either
single-step thru the programs or run the larger programs and
observe the results in the registers directly.(using the SEKA
assembler you can type "j program_name"to start the program.Then
you can read the results from the register directly,or use "q
address"to read it from memory.)
Lets start with an easy example,adding numbers in a table.
4.1.Adding Tables.
-----------------
Imagine that you have numbers in memory that you'd like to add.
Lets assume that you have five numbers whose length is one word
each.You want their sum to be written in register D0.The easiest
way to do this is:
;(4.1A)
adding1:
clr.l D0 ;Erase D0 (=0)
move table,d0 ;First entry in D0
add table+2,d0 ;Add second entry
add table+4,d0 ;Add third entry
add table+6,d0 ;Add fourth entry
add table+8,d0 ;add fifth entry
rts ;Return to main program
table: dc.w 2,4,6,8,10,
end
Try out the program using the debugger by single stepping thru the
program until you get to the RTS instruction(left Amiga T).(SEKA
owners use "j adding1").You see that data register D0 really
contains the sum of the values.
The method above only reads and adds numbers from a particular set
of addresses.The Amigas processor has lots of different sorts of
addressing modes that give us a shorter and more elegant solution.
Lets add a variable to the address of the table,so that the
program can add different tables.
Lets put the addresses of the table in an address register(for
example, A0)instead.This register can be used as a pointer to the
table.You must use move.l since only long words are relocatable.By
using a pointer to a table you can use indirect addressing.You can
change the expression "table+x" to"x(A0)".
;(4.1B)
adding1:
clr.l D0 ;Erase D0 (=0)
move.l #table,a0 ;Put table addresses in A0
move 0(a0),d0 ;Put first entry in d0
add 2(a0),d0 ;Add second entry
add 4(a0),d0 ;Add third entry
add 6(a0),d0 ;Add forth entry
add 8(a0),d0 ;Add fifth entry
rts ;Return to main program]
table: dc.w 2,4,6,8,10
end
Assemble this program,load it into the debugger.Then single step
(left Amiga T)thru this program and you'll see that this program
adds five numbers in order just like the last one.The reason you
used a step size of two for the ofset is that words are two bytes
long.AssemPro also defaults to relocate code so that you must move
#table as a long word.
Lets improve the program more by using "(a0)+"instead of "x(a)".
This way,every time you access elements of the table,the address
register A0 is automatically incremented by the number of bytes
that are read(in this case two).The difference between this and
the last example is that here the registers contents are modified.
The pointer is to the next unused byte or word in memory.
Lets make it even better.Lets make the number of words to be added
to a variable.You'll pass the number in register D1.Now you need
to do a different sort of programming,since you can't do it with
the old methods.
Lets use a loop.You need to add D1 words.You can use(a0)+ as the
addressing method(address register indirect with post increment),
since this automatically gets you to the next word.
Now for the loop.You'll have D1 decremented by one every time the
contents of the pointer are added.If D1 is zero,then you're done.
Otherwise,you need another addition.The program looks like this:
;(4.1C)
adding2:
clr.l d0 ;Erase D0
move.l #table,a0 ;Put table addresses in A0
move #$5,d1 ;Put number of entries in D1
loop: ;Label for loop beginning
add (a0)+,d0 ;Add a word
subq #1,d1 ;Decrement counter
bne loop ;Continue if non-zero
rts ;Else done
table: dc.w 2,4,6,8,10
end
Lets take a close look at this program.Load the pointer A0 with
the addresses of the data and the counter D1 with the number of
elements.Then you can single step thru the program and watch the
results.Make sure not to run the final command,the RTS command,
because otherwise a return address is popped from the stack,and
the results of this are unpredictable.(SEKA owners can use"x pc"
to point the program counter to "adding2".You can then step thru
the program by using the "s"command and watch the results).
To finish up this example,your assigning a little homework.Write
the program so that it adds single bytes or long words.Try to
write a program that takes the first value in a table and
subtracts the following values.For example,the table
table: dc.w 50,8,4,6
should return the value 50-8-4-6, ie 32 ($20).
4.2.Sorting a Table.
-------------------
Lets keep working with tables.You don't want to just read data
from one this time.You want to change it.You'll assort the table
in assending order.
You need to decide how to do the sorting.The simplest method is to
do the following.
Compare the first and the second value.If the second value is
larger than the first one,things are OK so far.Do the next step,
compare the second and third values,and so on.If you come to the
final pair and in each case the preceding value was smaller than
the following value,then the sorting is done(it was unnescessary).
If you find a pair where the second value is smaller than the
first,the two values are exchanged.You then get a flag(here let's
use a register)that is checked once you're done going thru the
table.If it is set,the table probably isn't completely sorted.You
then erase the flag and start again from the beginning.If the flag
is still zero at the end,the sorting is complete.
Now let's write a program to do this.First let's figure out the
variables you need.You'll use registers for the variables.You need
a pointer to the table you're sorting(A0),a counter(D0)and a flag
(D1).While the program is running,change these values,so you'll
need two more registers to store the starting values(address and
the number of the table entries).You'll use A1 and D2.
Let's start writing the program,each section will be written and
then explained.Then the complete program will be given.You put the
tables address in A1 and the number of entries in D2.
;(4.2A) part of sort routine
sort: ;Start address of the program
move.l #table,a1 ;Load pointer with address
move.l a1,a0 ;Copy pointer to working register
move.l #5,d2 ;Number in the counter
move.l d2,d0 ;Copy number of elements
subq #2,d0 ;Correct conter value
clr d1 ;Erase flag
table: dc.w 3,6,9,5
end
Now the preparations are complete.The pointer and the counter are
ready and the flag is cleared.The counter is decremented by two
because you want to use the DBRA command(take one off)and only X-1
comparrisons are needed for X numbers(take off one more).
Next let's write the loop that compares the values.You compare one
word with another.It looks like this:
loop:
move 2(a0),d3 ;Next value in register D3
cmp (a0),d3 ;Compare values
You need to use register D3 because CMP (A0),2(A0) isn't a legal
choice.If the second value is greater than or equal to the first
value,you can skip an exchange.
bcc noswap ;Branch if greater than or equal
;to
Now you need to do the exchanging(unfortunatly you can't use EXC
2(a0),(a0) since this form of addressing does not exist).
doswap:
move (a0),d1 ;Save first valus
move 2(a0),(a0) ;Copy second into first word
move d1,2(a0) ;Move first into second
moveq #1,d1 ;Set flag
noswap:
Now increment the counter and continue with the next pair.You do
this until the counter is negative.
addq.l #2,a0 ;Pointer+2
dbra d0,loop ;Continuing looping until the end
Now you'll see if the flag is set.You start again at the beginning
if it is.
tst d1 ;Test flag
bne sort ;Not finished sorting yet!
rts ;Otherwise done.Return
If the flag is zero,you're done and the subroutine ends.You jump
back to the main program using the RTS command.
Now a quick overview of the complete program.
;(4.2B)
sort: ;Start address of the program
move.l #table,a1 ;Load pointer with address
move.l a1,a0 ;Copy pointer to working register
move.l #5,d2 ;Number in the counter
move.l d2,d0 ;Copy number of elements
subq #2,d0 ;Correct counter value
clr d1 ;Erase flag
loop:
move 2(a0),d3 ;Next value in register D3
cmp (a0),d3 ;Compare values
bcc noswap ;Branch if greater than or equal to
doswap:
move (a0),d1 ;Save first value
move 2(a0),(a0) ;Copy second into first word
move d1,2(a0) ;Move first into second
moveq #1,d1 ;Set flag
noswap:
addq.l #2,a0 ;Pointer+2
dbra do,loop ;Continue looping until the end
tst d1 ;Test flag
bne sort ;Not finished sorting yet!
rts ;Otherwise done.Return
table:
dc.w 10,8,6,4,2 ;When finished acceding
end
To test this subroutine,assemble the routine with AssemPro,save it
and then load it into the debugger.The table is directly after the
RTS,notice its order.Set a breakpoint at the RTS,select the
address with the mouse and press left-Amiga-B sets a breakpoint in
AssemPro.Start the program the redisplay the screen by selecting
"Parameter-Display-Dissassem-bled"and examine the order of the
numbers in the table,they should now be ascending order.
You use several registers in this example for storing values.
Usually in machine language programming your subroutines cannot
change any register or can only change certain registers.For this
reason,there is a machine language command to push several
registers onto the stack at the same time.This is the MOVEM ("MOVE
multiple")command.If you insert this command twice in your program
then you can have the registers return to the main program with
the values they had when the subroutine was called.To do this,you
need one more label.Let's call it"start";the subroutine is started
from here.
start:
movem.l d0-d7/a0-a6,-(sp) ;save registers
sort:
etc...
...
...
bne sort ;not finished sorting yet!
movem.l (sp)+,d0-d7/a0-a6 ;retrieve registers
rts ;finished
The powerful command moves several registers at the same time.You
can specify which registers should be moved.If you want to move
the D1,D2,D3,D7,A2 and A3 registers,just write
movem.l d1-d3/d7/a2-a3,-(sp)
Before you quit sorting,do one little homework assignment.Modify
the program,so that it sorts the elements in descending order.
4.3.Converting Number Systems.
-----------------------------
As we mentioned in the chapter on number systems,converting
numbers from one base to another can be rather difficult.There is
another form of numeric representation-as a string that can be
entered via the keyboard or output on the screen.
You want to look at some of the many conversions possible and
write programs to handle the task.You'll start by converting a hex
number into a string using binary numbers and then print the value
in hex.
4.3.1.Converting Hex To ASCII.
-----------------------------
First you need to set the start and finish conditions.In this
example,let's assume that data register D1 contains a long word
that should be converted into a 8-digit long string of ASCII
characters.You'll write it to a particular memory location so that
you can output it later.
The advantage of using hex instead of decimal is pretty clear in
this example.To find out the hexadecimal digit for a particular
spot in the number,you just need to take the corresponting 4 bits
(half byte)and do some work on it.A half byte(also called a
nibble)contains one hex digit.
You'll work on a half byte in D2.To convert this to a printable
character,you need to use the correct ASCII code.The codes of the
16 characters that are used as hex digits are the following:
0 1 2 3 4 5 6 7 8 9 A B C D E F
$30 $31 $32 $33 $34 $35 $36 $37 $38 $39 $41 $42 $43 $44 $45 $46
To convert the digits 0-9,you just need to add $30.For the letters
A-F that correspond to the values 10-15,you need to add $37.The
program to evaluate a half byte must make a destinction between
values between 0 and 9 and those between A and F and add either
$30 or $37.
Now let's write a machine language subroutine that you'll call for
each digit in the long words hex representation.
nibble:
and #$0f,d2 ;just keep low byte
add #$30,d2 ;add $30
cmp #$3a,d2 ;was it a digit?
bcs ok ;yes:done
add #7,d2 ;else add 7
ok:
rts ;done
This routine converts the nibble in D2 to an ASCII character that
corresponds to the hex value of the nibble.To convert an entire
byte,you need to call the routine twice.Here is a program to do
this.The program assumes that A0 contains the address of the
buffer that the characters are to be put in and that D1 contains
the byte that is converted.
;(4.3.1a) bin-hex
; ;your program
lea buffer,a0 ;pointer to buffer
move #$4a,d1 ;byte to be converted(example)
bsr byte ;and convert
rts
; ... ;more of your program
byte:
move d1,d2 ;move value into d2
lsr #4,d2 ;move upper nibble into lower nibble
bsr nibble ;convert d2
move.b d2,(a0)+ ;put character into buffer
move d1,d2 ;value in d2
bsr nibble ;convert lower nibble
move.b d2,(a0)+ ;and put it in buffer
rts ;done
nibble:
and #$0f,d2 ;just keep low byte
add #$30,d2 ;add $30
cmp #$3a,d2 ;was it a digit?
bcs ok ;yes:done
add #7,d2 ;else add 7
ok:
rts ;done
buffer:
blk.b 9,0 ;space for long word data
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it intoi the debugger.Next set a breakpoint
at the first RTS,to set the breakpoint in AssemPro select the
correct address with the mouse and press the right-Amiga-B keys.
Start the program and watch the contents of D2,it is first $34
(ASCII 4)and finally $41(ASCII A).Select "Parameter-Display-HEX-
Dump"and you'll see that 4A has been moved into the buffer.
This is how the routine operates.First,you move the value that you
wish to convert into D2.Then you shift the register four times to
the right to move the upper nibble into the lower four bits.After
the subroutine call,you use "move.b d2,(a0)+"to put the HI nibble
in the buffer.Then the original byte is put in D2 again.It is
converted.This gives us the LO nibble as an ASCII character in D2.
You put this in the next byte of the buffer.
The buffer is long enough to hold a long word in characters and
closing the null byte.The null byte is usually required by screen
output routines.Screen output will be discussed in a later
chapter.Now let's worry about converting a long word.
When converting a long word,you need to be sure to deal with the
nibbles in the right order.Before calling the "nibble"routine for
the first time,you need to move the upper nibble into the lower 4
bits of the long word.You need to do this without losing anything.
The LSR command isn't very good for this application.If you use it
you'll lose bits.Its better to use the rotation commands like ROR
or ROL,since they move the bits that are shifted out,back in on
the other side.
If you shift the original long word in D1 four times to the left,
the upper four bits are shifted into the lower four bits.Now you
can use our "nibble"routine to evaluate it and then put the
resulting ASCII character in the buffer.You repeat this eight
times and the whole long word has been converted.You even have D1
looking exactly the way it did before the conversion process began
;(4.3.1B) bin-hex-2
hexlong:
lea buffer,a0 ;pointer to the buffer
move.l #$12345678,d1 ;data to convert
move #7,d3 ;counter for the nibbles:8-1
loop:
rol #4,d1 ;move upper nibble into lower
move d1,d2 ;write in d2
bsr nibble ;and convert it
move.b d2,(a0)+ ;character in buffer
dbra d3,loop ;repeat 8 times
rts ;finished!
nibble:
and #$0f,d2 ;just keep low byte
add #$30,d2 ;add $30
cmp #$3a,d2 ;was it a digit?
bcs ok ;yes:done
add #7,d2 ;else add 7
ok:
rts ;done
buffer:
blk.b 9,0 ;space for long word,null byte
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the first RTS,to set the breakpoint in AssemPro select the correct
address with the mouse and press the right-Amiga-B keys.Start the
program and when it is finished redisplay the output by selecting
"Parameter-Display-HEX-dump"so you can examine the new buffer
contents.
You'll find that there's an error in the program-the buffer
contains the digits "56785678"instead of "12345678".Try to find
the error.
Have you found it?This is the sort of error that causes you to
start pulling your hair out.This sort is hard to find.The
assembler assumes that the rotation operation should be done on a
word,because the ".l"was left off.As a result,only the lower word
of D1 was rotated-so you get the same value twice.If you change
the "rol.l",things work just right.
The error shows how easy it is to convert the program above into
one that converts four digit hex numbers into ASCII characters.
Just leave off the ".l"on the "rol"command and change the counter
from seven to three.The program is done.
Now for a little homework:change the program so that it can handle
six digit hex numbers(D1 doesn't nescessarily have to stay the
same...)!
Now lets look at a different conversion problem:converting a four
digit decimal number.
4.3.2.Converting Decimal To ASCII.
---------------------------------
It's not quite as easy to convert decimal as hex.You can't group
the bits to form individual digits.You need to use another method.
Lets look at how a decimal number is constructed.In a four digit
number,the highest place is in the thousands place,the next is the
hundreds place,etc...
If you have the value in a register and divide by 1000,you'll get
the value that goes in the highest place in the decimal number.
Since the machine language command DIV not only gives us the
result of the division but also gives us the remainder,you can
work out the remainder quite easily.You divide the remainder by
100 to find the hundreds place,divide the remainder by 10 and get
the tens place,and the final remainder is the ones place.
This isn't so hard after all!Heres the program that follows the
steps above to fill the buffer with D1's ASCII value.
main:
lea buffer,a0 ;pointer to the buffer
move #1234,d1 ;number to convert
jsr deci_4 ;test subroutine
illegal ;room for breakpoint
deci_4: ;subroutine-four digit numbers
divu #1000,d1 ;divide by 1000
bsr digit ;evaluate result-move remainder
divu #100,d1 ;divide by 100
bsr digit ;evaluate result and move
divu #10,d1 ;divide by 10
bsr digit ;evaluate result-move remainder
;evaluate the remainder directly
digit:
add #$30,d1 ;convert result into ASCII
move.b d1,(a0)+ ;move it into buffer
clr d1 ;erase lower word
swap d1 ;move the remainder down
rts ;return
buffer:blk.b 5,0 ;reserve bytes for result
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the illegal instruction.To set the breakpoint in AssemPro select
the correct address with the mouse and press the right-Amiga-B
keys.This breakpoint stops the program.Start the program and when
it is finished redisplay the output by selecting"Parameter-Display
-HEX-dump"so you can examine the ASCII values now in the buffer.
You use a little trick in this program that is typical for machine
language programming.After calling"digit"three times from the sub-
routine"deci_4",you go right into the"digit"subroutine.You don't
use a BSR or JSR command.Once the processor hits the RTS command,
it returns to the main program,not the "deci_4"subroutine.Doing
this,you save a fourth "bsr digit"command and an "rts"command for
the "deci_4"routine.
Try the program out.Make sure that you use values that are smaller
than 9999,because otherwise strange things can happen.
Now let's reverse what you've been doing and convert strings into
binary numbers.
4.3.3.Converting ASCII To Hex.
-----------------------------
In a string,each hex digit represents a half byte.You just need to
write a program that exactly reverses what the hex conversion
program did.
You have two choices
1. The number of hex digits is known in advance
2. The number is unknown
The first is easier to program,but has the disadvantage that if,
you assume the strings are four digits in length and want to enter
the value 1,you must enter 0001.That is rather awkward,so you'll
use the second method.
Let's convert a single digit first.You'll pass a pointer to this
digit in address register A0.You want the binary value to come
back in data register D0.
The program looks like this:
move.l #string,a0 ;this example
jsr nibblein ;test routine
nop ;set breakpoint here
nibblein: ;*convert the nibble from (A0)
clr.l d0 ;erase D0
move.b (a0)+,d0 ;get digit,increment A0
sub #'A',d0 ;subtract $41
bcc ischar ;no problem:in the range A-F
add #7,d0 ;else correct value
ischar:
add #10,d0 ;correct value
rts
string:dc.b 'B',0 ;character to convert
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the first NOP,to set the breakpoint in AssemPro select the correct
address with the mouse and press the right-Amiga-B keys.Start the
program and watch the contents of D0.
Let's see how the program works.A0 points to a memory location
that contains the character "B"that is represented by the ASCII
value $42.This number is loaded into D0 right after this register
is erased.
After subtracting $41,you end up with the value $1.Now you're
almost done.Before returning to the main program,you add 10 to get
the correct value 11,$B.
If the buffer has a digit in it,the subtraction causes the
register to become negative.The C flag is set.Let's take the digit
5 as an example.
The ASCII value of 5 is $35.After subtracting $41,you end up with
-12 and the C flag is set.In this case,you won't branch with the
BCC command.Instead you'll add 7 to get -5.Then 10 is added,and
you end up with 5.Done!
The routine as a disadvantage.If an illegal character is given,one
that doesn't represent a hex digit,you'll get some nonsense result
Let's ignore error checking for the moment though.
Let's go on to multi-digit hex numbers.The first digit that you
convert has the highest value and thus represents the highest
nibble.To allow for this and to allow for an arbitrarily long
number(actually not arbitrarily long,the number should fit in a
long word-so it can only be eight digits long),you'll use a trick.
Take a look at the whole program.It handles the calculations and
puts the result in D1.It assumes that A0 is a pointer to a string
and that this string is ended by null byte.
hexin: ;converting a hex number
clr.l d1 ;first erase D1
move.l #string,a0 ;address of the string in A0
jsr hexinloop ;test subroutine
nop ;set breakpoint here
hexinloop:
tst.b (a0) ;test digit
beq hexinok ;zero,then done
bsr nibblein ;convert digit
lsl.l #4,d1 ;shift result
or.b d0,d1 ;insert nibble
bra hexinloop ;and continue
hexinok:
rts
nibblein:
clr.l d0 ;convert the nibble from (A0)
move.b (a0)+,d0 ;get digit,increment A0
sub #'A',d0 ;subtract $41
bcc ischar ;no problem:in range A-F
add #7,d0 ;else correct value
ischar:
add #10,d0 ;correct value
rts
string:DC.B "56789ABC',00 ;eight digit string,null byte
;to be converted
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the NOP,to set the breakpoint in AssemPro select the correct
address with the mouse and press the right-Amiga-B keys.Start the
program and watch the contents of D1,the hex value is placed in
this register.
The trick is to shift left four times,to shift one nibble.In this
way,the place of the last digit is incremented by one and there is
room for the nibble that comes back from the "nibblein"routine.The
program uses the TST.B instruction to check for the null byte at
the end of the string,when it encounters the null byte the program
ends.The result is in the D1 long word already!
To do some error checking,you need to make some changes in the
program.You'll do this right after you come back from the"nibblin"
routine with the value of the current character.
If the value in D0 is bigger than $F,there is an error.You can
detect this in several ways.You chose the simplest one-you'll use
CMP #$10,D0 to compare D0 with $10.If it smaller,then the C flag
is set(since CMP uses subtraction)and everything is fine.If C is
zero,there is an error.
You can use this trick to skip the test for a null byte,since its
an invalid character as well.The program looks like this:
;(4_3_3C) hex-conv2 optional disk name
hexin: ;converting a hex number
clr.l d1 ;first erase D1
move.l #string,a0 ;address of string in A0
jsr hexinloop ;test subroutine
nop ;set breakpoint here
hexinloop:
bsr nibblein ;convert digit
cmp $10,d0 ;test if good
bcc hexinok ;no,then done
lsl.l #4,d1 ;shift result
or.b d0,d1 ;insert nibble
bra hexinloop ;and continue
hexinok:
rts
nibblein: ;convert the nibble from (A0)
clr.l d0 ;erase D0
move.b (a0)+,d0 ;get digit,increment A0
sub #'A',d0 ;subtract $41
bcc ischar ;no problem:in the range A-F
add #7,d0 ;else correct value
ischar:
add #10,d0 ;correct value
rts
string:DC.B "56789ABC',00 ;8 digit string ending with a
;null byte to be converted
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the NOP,to set the breakpoint in AssemPro select the correct
address with the mouse and press the right-Amiga-B keys.Start the
program and watch the contents of D1,the hex value is placed in
this register.
This is the method for converting hex to binary.If you convert
decimal to binary,the conversion is not much harder.
4.3.4.Converting ASCII To Decimal.
---------------------------------
You can use a very similar method to the one used above.Since you
are not sure how many digits there are,you'll use a similar method
for putting digits of a number in the next place up.You can't do
this with shifting,but you can multiply by 10 and add the value of
the digit.
Heres the program for converting decimal numbers.
decin: ;converting a decimal number
clr.l d1 ;first erase D1
move.l #string,a0 ;the string to convert
jsr decinloop ;test subroutine
nop ;breakpoint here
decinloop:
bsr digitin ;convert digit
cmp #10,d0 ;test,if valid
bcc decinok ;no,then done
mulu #10,d1 ;shift result
add d0,d1 ;insert nibble
bra decinloop ;and continue
decinok:
rts ;end of conversion
digitin: ;converting the nibble from (A0)
clr.l d0 ;erase D0
move.b (a0)+,d0 ;get digit,increment A0
sub #'0',d0 ;subtract $30
rts
string:dc.b '123456' ;ASCII decimal string to convert
end
To test this subroutine,use AssemPro to assemble the routine,save
the program and load it into the debugger.Next set a breakpoint at
the NOP,to set the breakpoint in AssemPro select the correct
address with the mouse and press thr right-Amiga-B keys.Select
"Parameter-Output-numbers-Decimal"so the registers are displayed
as decimal numbers.Then start the program and watch the contents
of D1,the decimal value is placed in this register.
This program can ONLY convert numbers upto 655350,although the hex
conversion routine can go higher.Thats because the MULU command
can only multiply 16-bit words.The last multiplication that can be
done correctly is $FFFF*10--65535*10,which gives us the value
655350.Normally this is a large enough range,so you won't
complicate the program further.