[comp.lang.postscript] The peek operator

cnwietho@immd4.informatik.uni-erlangen.de (Carsten Wiethoff) (09/21/89)

Hi folks!

This is for those who always wanted to know every single bit of their
PostScript(tm) laser printer: THE "peek" OPERATOR!

It is one of the most trivial applications of the "cexec" operator.
Since the program is written in 680x0 assembler and depends on the Adobe
"cexec" interface it should run only on laser printers with such a CPU
and a PostScript(tm) interpreter from Adobe or compatible to Adobe's .
(are there any others?)

Ah, before I forget it:
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
It may or may not be legal to run this program with the intent to
read out the contents of the ROMs, since these probably(?) contain
copyrighted data. I DO NOT ENCOURAGE YOU TO USE THIS PROGRAM TO READ
OUT COPYRIGHTED DATA! When you are in doubt, see your local law-guru.
When you are still in doubt, don't use this program. Otherwise enjoy!
END OF WARNING

First comes the assembler source file as an example of an operator
definition written in assembler. At the end is the operator definition
in eexec/cexec format ready to "print" together with some examples.
The assembler program was written on a SUN 3. Other assemblers may differ.
To change the program and convert it to eexec/cexec format you will 
have to do the following: (there may be more elegant ways)
- assemble it (using "as"), having the checksum set to 0x0000.
- strip symbols (if any) and the a.out header (32 bytes on a SUN 3).
- calculate the checksum (0x10000 - the 16 bit sum of the program).
- write the checksum into the program and reassemble
- strip it again
- construct a file with the following contents:
<BEGIN here vvv>
currentfile <length of stripped a.out file> string readstring
<stripped a.out file>
{cexec} {pop ioerror} ifelse
currentfile closefile
<END here ^^^>
- convert this file to eexec format using the algorithm I described 
  some time ago in this newsgroup (actually you will have to use the
  inverse algorithm of the one that I described). If you don't have this,
  send email. If there is enough interest I will post a C program that 
  does the job.
- print it

So here goes the assembler source:
----------------------------------cut here -------------------------------
| This is a peek program written by Carsten Wiethoff 1989
| You may do with it what you want, as long as my name stays in it.
| It may look a little weird, 
| since I adapted some of the Adobe calling conventions
|
first:		.word	0x07a2		| checksum
		.word	0x3399
		.word	last-first	| total length
		.word	0x0001
		.word	0x0402
		.word	entry-first	| entry point
		.word	reloc-first	| begin of relocation table
		.word	reloc-relocend	| end of relocation table

entry:
		movl	sp@(4),a0
		lea	arg1,a1
		movl	a0,a1@+
		movl	a0@+,a1@+
		movl	a0@+,a1@+
		movl	a0@+,a1@+
		bra	main

peek:		linkw	a6,#0
		bsr	pop_int		| pop address
		movl	d0,a0
		clrl	d0
		movb	a0@,d0		| access byte
		movl	d0,sp@-		| push value
		movl	#0x01020000,sp@-| push object descriptor
					| 01=integer, 02=no exec perm.
		bsr	push_general	| push on postscript stack
		addqw	#8,sp
		unlk	a6
		rts

main:		linkw	a6,#0
		bsr	userdict
		movl	d0,a0
		movl	a0@(4),sp@-
		movl	a0@,sp@-
		bsr	begindict
		addqw	#8,sp
		pea	peek
		pea	stringpeek
		bsr	defineop
		addqw	#8,sp
		bsr	enddict
		unlk	a6
		rts

stringpeek:		.asciz	"peek"

| system jump ins go here
| The names reflect my opinion about what these routines do.
| I have no documentation about these routines, so reality may differ.
		.even
begindict:	movw	#0x50,a0
		bra	jump
enddict:	movw	#0x80,a0
		bra	jump
userdict:	movw	#0xa0,a0
		bra	jump
pop_int:	movw	#0xe0,a0
		bra	jump
push_general:	movw	#0xf4,a0
		bra	jump
defineop:	movw	#0x11c,a0
		bra	jump

jump:		addl	arg2,a0
		movl	a0@,a0
		jmp	a0@

		.align	2
arg1:		.long		0
arg2:		.long	 	0	| system entry table
arg3:		.long 		0
arg4:		.long 		0

		.align	2
reloc:					| relocation table
relocend:	.word 0x0000
last:

------------------------- cut here ------------------------------------
Here finally comes the ready-to-print version:
--------------------------- cut here ----------------------------------
%!
% This is the peek operator written by Carsten Wiethoff 1989
% You may do with it what you want, as long as my name stays in it.
currentfile eexec
c3c703843e75cc772962e3a7fadee742b39452c3b503845648fbd351ba27c4a1
0682e041c9fa0f16614f0c04877181ee76d9e6bd87dd247a2857ccb6913dfcc1
123775eeaaab500a019e4b76d978c6e8d2383c16ed2a02acd8642efa2196cff7
dd72fc7834e096060b4259609b4a5fe03e1bce5f86e8bde12c8cdc7ee13437bc
9f1006f84253a13ed0cb41556b44df020c314ff99564f537fd0460bf77c5ac7c
a1eecc3271f4caf473668cf7c41f60b4a6702411a68490f25a96700051b3545b
91abd0161e7260f62ef55f7ab6d4e850c6e745666d29e50b045b19e96b01de4b
c5e24a59fd822ce839a8769b3830615de0781dcb0ba368ca3c8f5ca2e281149b
1a17dff0db3506609bc70393ec8f6482d798654cc171370f0b
% the previous is equivalent to 
% /peek {<function>} def
% usage: <address:integer> peek -> <byte:integer>

% example:
16#00000000 peek ==

% more useful:

(start\n)print
/str 2 string def
/nullstr (00) def
/outstr 2 string def

/byte2hex
  {
    outstr 0 nullstr putinterval
    outstr exch
    16 str cvrs
    dup length 2 exch sub exch
    putinterval
    outstr
  }
def

16#40000000 1 16#4000000f 
  {
    peek 
    byte2hex
    print
    (\n)print
  }
for

------------------------- cut here -------------------------------------

The writing of the "poke" operator, when desired, is left as an exercise
for the reader.

Enjoy and remember the warning!

				Carsten Wiethoff
				c/o Frank Kardel

				Friedrich-Alexander Universitaet
				Erlangen-Nuernberg
				
				CS Department IMMD IV
				Martensstrasse 1
				D-8520 Erlangen
				---------------
				West Germany

Voice: +49/(0)9131/85-7908
E-mail: cnwietho@immd4.informatik.uni-erlangen.de

Private:                        Carsten Wiethoff
				Untere Karlstr.7
				D-8520 Erlangen
				West Germany

				Tel.: +49/(0)9131/29136