home *** CD-ROM | disk | FTP | other *** search
- (c) Copyright 1989-1999 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-1999 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
-
-
-
-