home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Developer CD v1.2
/
amidev_cd_12.iso
/
reference
/
amiga_mail_vol1
/
exec
/
asmdeviceio
next >
Wrap
Text File
|
1990-01-26
|
10KB
|
263 lines
(c) Copyright 1989 Commodore-Amiga, Inc. All rights reserved.
The information contained herein is subject to change without notice, and
is provided "as is" without warranty of any kind, either expressed or implied.
The entire risk as to the use of this information is assumed by the user.
Assembler Device IO - The Easy Way
Carolyn Scheppner
Amiga.lib contains a number of compiled C Exec support functions which
are used by C programmers to simplify the creation of tasks and ports
and the setup of IORequest structures. In addition, amiga.lib contains
a number of C support functions such as printf() and getchar(). These
functions are all documented in the Addison-Wesley Exec manual in
Appendix B, along with the C source of the Exec support functions.
Although these functions are only provided with a C interface, it is
relatively easy to call them from assembler. The Exec support functions
can greatly simplify assembler device IO and task creation code, and the
C support functions such as printf() are handy for simple formatted output
and debugging. Note that to use the amiga.lib stdio functions, you must
link with Astartup.obj or set up your own Amiga stdio file handles.
The general method for accessing the C interface amiga.lib functions
from assembler is as follows:
1. XREF the function name prepended with an underscore ("_")
2. Look at the C calling conventions for the function.
You will have to push the required arguments onto the stack
as longs, in right to left order as they appear in the C call.
If an argument is a literal string or string pointer, you
must push the address of a string that you have terminated
with a null. (See fstr DC.B in the DevIO.asm example.)
3. Assume that the contents of d0-d1/a0-a1 will be lost, so save
them if necessary. Push your arguments, as longs, onto the stack.
JSR _functionname, then add 4 to the stack pointer for each long
that you pushed on the stack. The function result is returned
in D0.
The DevIO.asm example source in this issue is commented so that you can
compare the C calling conventions with the assembler equivalents.
--------------------------- Example -------------------------------
* DevIO.asm
*
* Opening and talking to a device in mostly asm - Carolyn Scheppner
*
* Copyright 1988 Commodore-Amiga, Inc. All Rights Reserved
*
* Opens gameport.device unit 0 and asks gameport what controller type
* gameport 0 is set to (1=mouse)
*
* Demonstrates assembler use of the compiled C exec support
* routines (CreatePort, etc.) in amiga.lib, and also the use of
* amiga.lib csupport functions such as _printf for simple formatted
* output and debugging.
*
* Outputs address of port
* address of iob
* return of Opendevice (0=success)
* controller type (1=mouse)
*
* LINK INSTRUCTIONS: Alink with Astartup.obj ... LIBRARY amiga.lib
* (Astartup sets up the stdout needed for amiga.lib _printf, etc.)
*
INCLUDE "exec/types.i"
INCLUDE "exec/io.i"
INCLUDE "libraries/dos.i"
INCLUDE "devices/gameport.i"
** Imported Labels **
*------ from Astartup.obj
XREF _AbsExecBase
XREF _SysBase
*------ System function Library Vector Offsets
XREF _LVOOpenDevice
XREF _LVOCloseDevice
XREF _LVOSendIO
XREF _LVOWait
XREF _LVOGetMsg
*------ C interface Exec Support functions in amiga.lib
XREF _CreatePort
XREF _DeletePort
XREF _CreateStdIO
XREF _DeleteStdIO
*------ C interface C Support functions in amiga.lib
XREF _getchar
XREF _printf
** Exported Labels **
*------ Where Astartup.obj JSR's to our code
XDEF _main
CODE
** Code **
_main:
movem.l d2-d7/a2-a6,-(sp) ;Save the registers
*----- Exec Support function: msgPort = CreatePort(name,pri)
* Used to create the replyPort for our messages
move.l #0,-(sp) ;push priority 0 on stack as long
pea portname ;push addr of my null-termed portname
jsr _CreatePort ;call CreatePort
addq.l #8,sp ;add 4 to stack for each long pushed
jsr mydebug0 ;my print d0 debugging rtn
move.l d0,myport ;save result
beq failure ;if zero, CreatePort failed
*----- Exec Support function: ioReq = CreateStdIO(ioReplyPort)
* Note - many other devices use special extended IO requests
* which are defined in the include file for the device.
* If a larger request is required, you must use
* _CreateExtIO(ioReplyPort,size) and _DeleteExtIO(ioReq)
move.l d0,-(sp) ;push d0 (still holds port from above)
jsr _CreateStdIO ;call CreateStdIO
addq.l #4,sp ;add 4 to stack for the long pushed
jsr mydebug0 ;my print d0 debugging rtn
move.l d0,myiob ;save result
beq failure ;if zero, CreateStdIO failed
*----- The normal assembler _LVO method is used to call system routines
*----- Open the device
move.l d0,a1 ;iorequest returned above
lea.l devname,a0 ;null terminated device name
moveq #0,d0 ;unit 0
moveq #0,d1 ;flags
move.l _SysBase,a6 ;prepare to call Exec function
jsr _LVOOpenDevice(a6) ;call OpenDevice
jsr mydebug0 ;my print d0 debugging rtn
tst.l d0 ;check for 0 (success) of OpenDevice
bne failure ;branch if OpenDevice failed
move #1,gotdev ;else set flag that it was successful
*----- Build waitmask of 1 << myport->mp_SigBit
moveq #0,d0 ;clear d0
movea.l myport,a0 ;myport to a1
move.b MP_SIGBIT(a0),d0 ;get sigbit number from myport
moveq #1,d1 ;put 1 in d1
lsl.l d0,d1 ; and shift left (1 << sigbit)
move.l d1,waitmask ; to create waitmask for our Wait
*----- Set up our command as specified in gameport device autodocs
movea.l myiob,a1 ;myiob to a1 to set up command
move.w #GPD_ASKCTYPE,IO_COMMAND(a1) ;our command
move.l #1,IO_LENGTH(a1) ;as per autodocs
move.l #result,IO_DATA(a1) ;address of byte for result
*----- Send the command, Wait for the reply, the GetMsg the reply
* Note that
move.l _SysBase,a6 ;set up for an Exec call
jsr _LVOSendIO(a6) ;call SendIO, myiob already in a1
move.l waitmask,d0 ;CreatePort'd port is a signal port
jsr _LVOWait(a6) ;So I wait for the signal
movea.l myport,a0 ;then get the message
jsr _LVOGetMsg(a6)
moveq #0,d0 ;clear d0 since result is a byte
move.b result,d0 ;move result to d0
jsr mydebug0 ;my print d0 debugging rtn
*----- If you uncomment this, program will wait till you hit <RETURN>
* A loop of _getchar calls can be used to simulate a gets().
* Just store each d0 returned in an array until you get a 10 ('\n').
* Then null terminate the string.
* jsr _getchar ;waits for <RET> in case you want to wack
*----- Code was successfully executed
move.l #RETURN_OK,retcode ;set up success return code
bra.s cleanup ;and skip to cleanup code
*----- Failures in earlier code will branch here
failure:
move.l #RETURN_FAIL,retcode ;set up success return code
cleanup:
tst.l gotdev ;if OpenDevice was unsuccessful
beq nodev ; skip CloseDevice
move.l _SysBase,a6 ;else set up for Exec call
move.l myiob,a1 ;ioReq to a1
jsr _LVOCloseDevice(a6) ;call CloseDevice
nodev
move.l myiob,d0 ;if CreateStdIO was unsuccessful
beq noiob ; skip DeleteStdIO
*----- Exec Support function: DeleteStdIO(ioReq)
move.l d0,-(sp) ;else push d0 (now our ioReq)
jsr _DeleteStdIO ;call DeleteStdIO
addq.l #4,sp ;add 4 to stack for pushed long
noiob
move.l myport,d0 ;if CreatePort was unsuccessful
beq noport ; skip DeletePort
*----- Exec Support function: DeletePort(port)
move.l d0,-(sp) ;else push d0 (now our msgPort)
jsr _DeletePort ;call DeletePort
addq.l #4,sp ;add 4 to stack for pushed long
noport
movem.l (sp)+,d2-d7/a2-a6 ;Restore registers
move.l retcode,d0 ;Put our return code in d0
rts ;rts
*----- mydebug0 - uses amiga.lib _printf to print the contents of d0
* I preserve d0-d1/a0-a1/a6
mydebug0:
movem.l d0-d1/a0-a1/a6,-(sp) ;save these registers
*----- C Support function printf(): here printf("$%lx\n",contents_of_d0)
* Note that the fstr DC.B below specifies '\n' and null as 10,0
move.l d0,-(sp) ;push d0 on the stack
pea fstr ;push addr of format string
jsr _printf ;call printf
addq.l #8,sp ;add 4 to stack for each long
movem.l (sp)+,d0-d1/a0-a1/a6 ;restore the saved registers
rts ;rts
DATA
CNOP 0,4
myiob DC.L 0
myport DC.L 0
gotdev DC.L 0
waitmask DC.L 0
retcode DC.L 0
result DC.B 0
portname DC.B 'cas_devport',0
devname DC.B 'gameport.device',0
fstr DC.B '$%lx',10,0
END