home *** CD-ROM | disk | FTP | other *** search
- ;**************************************************************************
- ; CLIprint.asm by Jeff Glatt
- ;
- ; Some people just starting out in assembly always ask about printing to the
- ; CLI. This program demonstrates how to do that.
- ;
- ; An example of printing to the CLI. Must be linked with a startup code that
- ; sets up a variable, _stdout. This variable is the result of a call to
- ; dos lib's Output() function, and is the fileHandle of the CLI window from
- ; where this program was started. If this program was started from WorkBench
- ; then _stdout will be 0. The provided startup code called StartUp.o has
- ; been provided for linking with this example. Using BLink,
- ;
- ; Blink StartUp.o CLIprint.o small.lib TO CLIPrint
- ;
- ; This program does the following:
- ; 1). Does a straight print of a string using dos lib's Write().
- ; 2). Does a print of a NULL-terminated string using an included function
- ; printf. The printf function has the facility to do more than just
- ; print a string. By including format specifiers in the string, a "new"
- ; string is created with additional information in it. A format specifier
- ; is a % character followed immediately by one of the following letters:
- ; lc - for a character (pass the character on the stack)
- ; ls - for a string (pass the string's starting address on the stack)
- ; ld - for a signed decimal representation (pass the 32 bit value on the stack)
- ; lx - for a hex representation (pass 32 bit value on stack)
- ; See page B-17 of the Exec ROM Kernal manual for additional options.
- ; For example, let's say that we have the string
- ;
- ;Message dc.b 'The number = %ld',0
- ;
- ; printf would not output the '%ld' part of the string to the CLI. Instead,
- ; it would create a new string where the '%ld' would be replaced by a number
- ; that you passed on the stack. This number would be represented as an ascii
- ; string. So, using the above string, we called printf like so:
-
- ; lea Message,a0 ;the specifier string goes in a0
- ; moveq #50,d0 ;let's pass the number 50 as a 32 bit value to printf
- ; move.l d0,-(sp)
- ; bsr printf
- ; addq.l #4,sp ;re-adjust for pushing the 50
-
- ; Now printf would print this to the CLI
- ;
- ;The number = 50
-
- ; 3). Demonstrates calls to printf with imbedded specifiers.
-
- ;from StartUp.o
- XREF _stdout,_DOSBase,_SysBase
-
- ;from small.lib
- XREF _LVOWrite,_LVORawDoFmt
-
- SECTION printfdata,DATA
-
- Message1Len equ 32 ;don't count terminating NULL
- Message1 dc.b 'This is a print using Write().',13,10,0
-
- Message2 dc.b 'This is a print using printf().',13,10,0
-
- Format1 dc.b 'The number passed to printf = %ld',13,10,0
-
- Format2 dc.b 'The string passed to printf is "%ls".',13,10,0
- StringInside dc.b 'Hello',0
-
- Format3 dc.b 'The number is %ld, and string = %ls',13,10,0
-
- Format4 dc.b 'The number in hex = $%lx',13,10,0
-
- FinalMsg dc.b 'Understand, Bozo?',13,10,0
-
- SECTION printfcode,CODE
-
- XDEF _main ;the first routine you want executed must be called _main.
- _main:
- ;---Output a straight string via Write()
- lea Message1,a0
- move.l a0,d2
- moveq #Message1Len,d3
- move.l _stdout,d1
- movea.l _DOSBase,a6
- jsr _LVOWrite(a6)
- ;---Output a straight string via printf
- lea Message2,a0
- bsr printf
- ;---Output a number inside of the string specifier via printf
- lea Format1,a0
- moveq #50,d0
- move.l d0,-(sp)
- bsr printf
- addq.l #4,sp
- ;---Output that number again (but use the hex specifier)
- lea Format4,a0
- moveq #50,d0
- move.l d0,-(sp)
- bsr printf
- addq.l #4,sp
- ;---Output a string inside of the string specifier via printf
- lea StringInside,a1
- move.l a1,-(sp)
- lea Format2,a0
- bsr printf
- addq.l #4,sp
- ;---Output a string and number inside of the string specifier
- ; The order to push the args is reverse to the order that they are inserted
- ; into the string (i.e. my %ld came before my %s, so I push StringInside
- ; first then the number 50)
- lea StringInside,a1
- move.l a1,-(sp)
- moveq #50,d0
- move.l d0,-(sp)
- lea Format3,a0
- bsr printf
- addq.l #8,sp ;note: re-adjust for 2 LONG pushes
- ;---One last insult
- lea FinalMsg,a0
- bsr printf
- ;---Get out of this program
- rts
-
- ;=======================================================================
- ; Pass string specifier in a0, and any args on the stack.
-
- XDEF printf
- printf:
- ;---If we're from WorkBench, _stdout = 0. Get out of here.
- move.l _stdout,d0
- beq.s noPF
- ;---Get the address of where we pushed any args in a1
- lea 4(sp),a1
- ;---Save some regs
- movem.l d2/d3/a2/a3/a4/a6,-(sp)
- ;---Save the address of stdout
- movea.l d0,a4
- ;---Get a buffer on the stack to create a "new" string
- ; Now we call Exec's RawDoFmt. It does all the work of formatting
- ; the new string. It needs the address of a function we create. This
- ; function just throws a char into our "new" buffer. Exec calls this
- ; for every "new" character it creates.
- moveq #126,d0
- suba.l d0,sp
- lea StoreChar,a2
- movea.l sp,a3
- ;address of args in a1
- movea.l _SysBase,a6
- jsr _LVORawDoFmt(a6)
- ;---Count how many chars are in the string (it will be NULL-terminated)
- moveq #126-1,d1
- move.l a3,d2 ;the start of our "new" string
- cntC move.b (a3)+,d0
- Dbeq d1,cntC(pc)
- ;---Determine # of chars
- subq.l #1,a3
- move.l a3,d3
- sub.l d2,d3
- beq.s char0 ;if 0 chars, don't print anything
- ;---Print out to _stdout (which will be the CLI window unless the user
- ; redirected output on the command line using the '>')
- move.l a4,d1
- ;address of string in d2
- movea.l _DOSBase,a6
- jsr _LVOWrite(a6)
- ;---Get rid of our "new" buffer
- char0 moveq #126,d0
- adda.l d0,sp
- ;---Restore regs
- movem.l (sp)+,d2/d3/a2/a3/a4/a6
- noPF rts
-
- ;Exec passes a "new" character (in d0) to be stored in our "new" buffer
- ;(address in a3).
- StoreChar move.b d0,(a3)+
- rts
-