„Amiga Machine Language (Chapter 8)” 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:37-kori változata
Chapter 8.
----------
8.Advanced Programming.
-----------------------
You've learned a lot about machine language programming on the
Amiga.What you need yet are a few routines that can be used as
programming tools.We'll work on that right now.They'll be easy to
use in your own program.The sky's the limit now!
8.1.Supervisor Mode.
--------------------
As mentioned in the chapter on the MC68000 processor,there are two
operating modes:the User and the Supervisor mode.It is often
necessary to move between the two modes.However,this isn't a
simple process.
The reason you want to do this,is that in User mode,you can't
access the Status register.If you write to one of them,an
Exception is executed which crashes the program.
How can you get in Supervisor mode?
No problem.The operating system of the Amiga contains a function
in the EXEC library that lets you get into supervisor mode.Its
called SuperState and it doesn't need any parameters.You can
easily call this program by using the following lines:
execbase = 4 ;exec base address
superstate =-150 ;turn on function
...
move.l execbase,a6 ;exec base address in A6
jsr superstate(a6) ;turn on supervisor mode
move.l d0,savesp ;save return value
...
savesp:blk.l 1 ;space for sp value
You get the value of the Stack Pointer(SP)back in the D0 register.
You'll also find it in register A7,but this register is changed
regularly.The reason is that in Supervisor mode,the Amiga works
with all the Interrupts and with the SP,and there are lots of
Interrupts for this computor.We'll talk about interrupts in a bit.
After this call,you'll use the user stack instead of the
supervisor stack.In this way,you can access the old user stack.You
need to make sure that the user stack is large enough since the
interrupts must have enough room for their data on the stack.
You need to save the value returned in D0,because you'll need this
value later.You need to return to user mode sometime.Theres a
function for this in the exec library as well.It is called the
UserState function.It needs one parameter,the SP value that comes
back from the SuperState function.
Since you've saved this value in the long word starting at
"savesp",you can write the following:
userstate =-156
...
move.l execbase,a6 ;exec base address in A6
move.l savesp,d0 ;put old sp in D0
jsr userstate(a6) ;return to user mode
Now you are back in the user mode.The user stack point(USP)is the
same as before.You can write functions that need to be run from
the supervisor mode as subroutines.First you call superstate,save
the return value,execute the desired function,call userstate,and
end with a RTS command.If the USP was changed,the RTS command
would'nt work right,and the computor would jump who knows where
and perhaps crash.Here it works though.
Now comes the question:how does the operating system get the
supervisor mode?Thats not too difficult;it goes like this:
The superstate function attempts to access a Status Register.This
causes an Exception to occur and a routine is called whose address
begins at the long word starting at $20.It is the Exception Vector
for Privilege Violation.The routine that it branches to is called
in supervisor mode.Then it tests where this exception came from.If
the routine finds that the exception comes from the superstate
routine whose address it knows,the matter is settled.It just
branches to the routine without turning off the user mode.Thats
all there is to it.
8.2.Exception Programming.
--------------------------
The exceptions described in the processor chapter offer you a lot
of oppertunities to control the Amiga's functions.You can use them
to specify how errors should be handled and even list a crash
program.
Here is a list of vectors that are used to jump to the exception
routines:
Number Address Use with
------------------------------------------------------------------
2 $008 Bus error
3 $00C Address eror
4 $010 Illegal command
5 $014 Division by zero
6 $018 CHK command
7 $01C TRAPV command
8 $020 Privilege Violation
9 $024 Trace
10 $028 Axxx command emulation
11 $02C Fxxx command emulation
$030-$038 Reserved
15 $03C Uninitialized interrupt
$040-$05F Reserved
24 $060 Unauthorised interrupt
25-31 $064-$083 Level 1-7 interrupt
32-47 $080-$0BF TRAP commands
$0C0-$0FF Reserved
64-255 $100-$3FF User interrupt vector
Lets look at the TRAP commands as an example.They aren't used in
the Amiga operating system.A TRAP command and a number between
zero and fifteen are used to call one of the 16 posible TRAP
routines.If the command TRAP #0 is executed,the processor (in
supervisor mode)branches to the routine whose address lies at $80
in memory.This routine must end with a RTE(ReTurn from Exception)
command.
Some operating systems,for example,the ATARI ST's TOS operating
systems,are completely callable via these TRAP's.Parameters are
put on the stack,and then a TRAP command is executed.The advantage
is that you don't have to know any of the operating systems
addresses.In the Amiga you must know the addresses(Execbase=4).
Lets write your own TRAP routine to demonstrate the use of the
TRAP command.You'll need three program sections:
1.The initialization of the TRAP vector.
2.The TRAP routine itself(It must end with RTE).
3.A test routine that calls the TRAP command.
Initialization is very short:
init:
move.l #trap0,$80 ;set vector for TRAP #0
rts
Now you need to write the trap0 routine.Lets use the example from
the hardware chapter that produced a beep.
Lets write this routine using as little effort as possible.Change
the RTS to a RTE at the end,erase the line in which the loop
counter D0 was loaded for the tone production,and change the loop
so that it works with long words.Now you can load the register
with an arbitrary value and have the TRAP #0 followed by a peep of
arbitrary duration.
;** beep tone production after a TRAP #0 **
ctlw =$dff096 ;DMA control
c0thi =$dff0a0 ;HI table address
c0tlo =c0thi+2 ;LO table address
c0tl =c0thi+4 ;table length
c0per =c0thi+6 ;read in rate
c0vol =c0thi+8 ;volume
trap0: ;* produce a short peep
move.l #table,c0thi ;table beginning
move #4,c0tl ;table length
move #300,c0per ;read in rate
move #40,c0vol ;volume
move #$8201,ctlw ;start DMA (sound)
loop:
subq.l #1,d0 ;counter -1
bne loop ;count dwn to zero
still:
move #1,ctlw ;turn on tone
rte ;exception end
table: ;sound table
dc.b -40,-70,-40,0,40,70,40,0
You need to make sure that "table"is in CHIP RAM($00000-$7FFFF),
otherwise the sound chip can't access the data!
After entering this,you can test it out using the following
routine:
test:
move.l #$2ffff,d0 ;pass tone length in D0
trap #0 ;carry out exception:peep
rts
Now assemble both routines and start the initialization routine,
init.Nothing happens.
Start the second routine,test.A beep that lasts about one second
is output.
One thing you must keep in mind is that if you change the program
and reassemble it,the address of the trap0 routine can change.
Before you execute the TRAP command,you must repeat the initializ-
ation,so that the computor doesn't jump to the wrong location!