;--------------------------------------------------------------- ; LISTRSX.ASM program to demonstrate techniques for ; investigating RSX's hooked into a CP/M+ system. ; When run from the command line, it prints out the ; names of all RSX's currently resident (not including ; any which have been disconnected by the CCP loader, ; but not removed), giving their entry point addresses ; in hex. ; ; Note that if any RSX's are hooked into the system, the ; CCP loader will always be present, and is accordingly ; shown by the program. The last address printed is the ; BDOS entry point - this will vary on different machines, ; and should never be assumed by the user. ; ; The program may be run from the command line simply by ; typing LISTRSX - no parameters are required. ; jp start ; db 'LISTRSX 1.2, (c) Andy Metcalfe 19/8/88. ' db 'This program is public domain, and commercial ' db 'sale or distribution is expressly prohibited' ; ;--------------------------------------------------------------- ; ASCII Codes ; lf equ 0ah ; Linefeed cr equ 0dh ; Carriage return ; ;--------------------------------------------------------------- ; CP/M Addresses ; bdos equ 0005h ; BDOS entry point ; ;--------------------------------------------------------------- ; BDOS Functions ; wboot equ 00h ; Warm boot CP/M conout equ 02h ; Print character strout equ 09h ; Print string to console getver equ 0ch ; Get CP/M version number scblk equ 31h ; Get/set System Control Block ; ;--------------------------------------------------------------- ; Main Program Follows ; start: ld a,cr call conchr ld a,lf call conchr ; Print ld c,getver call bdos ; Get version number cp 31h jp z,vplus ; OK if version 3.1 ; ld de,noplus ld c,strout call bdos ld c,wboot jp bdos ; Else print error message & reboot ; dseg noplus: db 'Sorry: requires CP/M+',cr,lf,'$' cseg ; vplus: ld de,scb3a ld c,scblk call bdos ; HL=base address of SCB dec hl dec hl dec hl ; Now points to high byte of BDOS entry addr ld b,(hl) ; B=high byte of BDOS entry addr ld a,(bdos+2) ; Start page of first RSX or BDOS cp b ; Compare: CY=0 if no RSX jp c,presnt ; Jump if RSX(s) present ld hl,(bdos+1) ; HL=BDOS entry point address call prbdos ; Print it ld de,nomes ld c,strout call bdos ; Print 'No RSX' message ld c,wboot jp bdos ; And warm boot CP/M ; dseg nomes: db cr,lf,'No RSX currently present',cr,lf,'$' cseg ; presnt: ld hl,(bdos+1) ; Address of first RSX in chain ex de,hl ; To DE xor a ld (endrsx),a ; End chain flag initially FALSE ; prloop: ld a,(endrsx) or a ; Test end of chain flag jp nz,endprt ; Reached end - print BDOS addr & warm boot ld a,d call phex ld a,e call phex ; Print address of RSX entry point ld a,' ' call conchr ; Print a space ld hl,18 ; Offset for loader flag add hl,de ld a,(hl) ; A=flag or a ; Test it ld (endrsx),a ; Store as end of search flag (TRUE=0ffh) ld hl,10 ; Offset for name add hl,de ex de,hl ; DE=start addr of next RSX's name ld b,8 ; 8 bytes to print prtnam: ld a,(de) call conchr inc de dec b jp nz,prtnam ; Loop until all 8 chars of name printed ; ld a,cr call conchr ld a,lf call conchr ; Print ex de,hl ld hl,4 add hl,de ; HL=next+1 for RSX just tested ld e,(hl) inc hl ld d,(hl) ; DE=start address for next RSX jp prloop ; Loop to print next one ; ; Jump here on completion ; Print BDOS entry point address, & warm boots CP/M. ; (BDOS entry point addr in reg DE). ; endprt: ex de,hl call prbdos ; Print entry point address ld c,wboot jp bdos ; Warm boot CP/M ; ; Print BDOS entry point address in HL, and "BDOS" ; prbdos: ld a,h call phex ld a,l call phex ; Print address of entry point ld de,sysnam ld c,strout jp bdos ; Print "BDOS" after address, and ret ; dseg sysnam: db ' BDOS',cr,lf,'$' ; endrsx: ds 1 scb3a: db 3ah,0 ; Word at offset 3ah gives base addr of SCB cseg ; ;--------------------------------------------------------------- ; Send char in A to console ; All registers & flags preserved ; conchr: push hl push de push bc push af ld e,a ld c,conout call bdos pop af pop bc pop de pop hl ret ; ;--------------------------------------------------------------- ; ; Print hex char in reg A ; All regs preserved ; phex: push af rrca rrca rrca rrca ; Divide by 16 call pnib ; Print upper nybble pop af jp pnib ; Print lower nybble & ret ; ; Subroutine: Print nybble in lower 4 bits of A ; pnib: push af and 0fh ; Mask out upper nybble cp 10 jp nc,p10 ; ; Value 0-9 ; add a,'0' jp prn ; ; Value 10-15 ; p10: add a,'A'-10 prn: call conchr ; Print nybble in hex pop af ret ;