- Исходник printf()
-
? Patron - 09.02.2011 17:45
.title printf Formatted print routine
¤
;
; The information in this document is subject to change
; without notice and should not be construed as a commitment
; by Digital Equipment Corporation or by DECUS.
;
; Neither Digital Equipment Corporation, DECUS, nor the authors
; assume any responsibility for the use or reliability of this
; document or the described software.
;
; Copyright (C) 1980, DECUS
;
;
; General permission to copy or modify, but not for profit, is
; hereby granted, provided that the above copyright notice is
; included and reference made to the fact that reproduction
; privileges were granted by DECUS.
;
.ident /000002/
;
;+
;
; Usage
;
; printf(format, arg1, ...);
; char *format;
;
; fprintf(iov, format, arg1, ...);
; FILE *iov;
; char *format;
;
; sprintf(buffer, format, arg1, ...);
; char *buffer;
; char *format;
;
; Description
;
; printf() converts, formats, and prints its arguments, under control
; of the first argument, writing output via putchar(). fprintf()
; writes its output to the indicated file. sprintf() writes its
; output to the indicated string buffer.
;
; The first argument is a character string which contains two
; types of objects: plain characters, which are simply copied
; to the output stream, and conversion specifications, each of
; which causes conversion and printing of the next successive
; argument to printf.
;
; Each conversion specification is introduced by the character %.
; Following the %, there may be
;
; - an optional minus sign "-" which specifies left
; adjustment of the converted argument in the indicated
; field.
;
; - an optional digit string specifying field width; if
; the converted argument has fewer characters than the
; field width, it will be blank-padded on the left (or
; right, if the left-adjustment indicator has been
; given) to make up the field width. If the field
; width is given as '?', the next argument is used.
;
; - an optional period "." which serves to separate the
; field width from the next digit string;
;
; - an optional digit string (precision) which specifies
; the number of digits to appear after the decimal
; point for e- and f-conversion, or the maximum number
; of characters to be printed from a string. If the
; precision is given as '?', the next argument is used.
;
; - a character which indicates the type of conversion
; to be applied.
;
; The conversion characters and their meanings are
;
; d Signed-decimal
; u Unsigned-decimal
; o Octal
; X Hexadecimal, 10-15 are represented by A-F
; x Hexadecimal, 10-15 are represented by a-f
;
; The integer argument is converted to decimal,
; octal, or hexadecimal notation respectively.
; Any of the conversion characters may be
; preceeded by 'l' to signal "long" integer
; argument. Note that the Unix usage of capital
; letters to represent long arguments is not
; supported.
;
;
;- f The argument is converted to decimal notation
;- in the style "[-]ddd.dd" where the number of d's
;- after the decimal point equals the precision
;- specification for the argument. If precision is
;- missing, 6 digits are given; if explicitly 0, no
;- digits and no decimal point are printed. The
;- argument should be float or double.
;-
;- e The float or double argument is converted in the
;- style "[-]d.ddde+-dd" where there is one digit
;- before the decimal point and the number after is
;- equal to the precision specified for the
;- argument; if the precision is missing, 6 digits
;- are produced.
;-
;- g e or f format for double argument,with depend of
;- number of digits in mantiss.
;-
; c The argument character is printed. (Note that
; 'lc' takes a long integer argument.)
;
; r Remote format. The next printf() argument is
; the format. Note that this is not a subroutine.
; The current format is not processed further. For
; example:
;
; bug(args)
; {
; error("Error at %r", &args);
; }
;
; This routine might be called as follows:
;
; bug("Error %d at %s\n", val, name);
;
; s The argument is taken to be a string (character
; pointer) and characters from the string are
; printed until a null character or until the
; number of characters indicated by the precision
; specification is reached; however if the
; precision specification is 0 or missing all
; characters up to null are printed.
;
; If no recognizable character appears after the %, that character
; is printed; thus % may be printed by the use of the string %%.
; In no case does a non-existant or small field width cause truncation
; of a field; padding takes place only if the specified field
; width exceeds the actual width. Characters generated by printf()
; are printed by calling putchar().
;
; Bugs
;
; e, f, and g conversion haven't been written yet.
;-
;
; Edit history
; 000001 05-Mar-80 MM Initial edit
; 000002 22-May-80 MM Fout -> stdout
;
¤
;
; Autos.
;
;
; Note: these values are compiled as c$$auto - number. If c$$auto
; changes, these must also.
;
¤
auto$$ = -6 ; See csv.mac for the correct value ;01+
¤
FUNC = auto$$-2
ARGP = auto$$-4
LJUST = auto$$-6
PREC = auto$$-10
WIDE = auto$$-12
FILL = auto$$-14
HORD = auto$$-16
LORD = auto$$-20
BUF = auto$$-44 ; 20 bytes.
OLDP = auto$$-46
STACK = 46 ; Last argument for stack get ;01-
¤
.psect .data.
¤
null: .asciz "{Null}"
.even
¤
.psect .prog.
¤
printf::
jsr r5,csv$
mov #$$putc,r1 ;01+
mov stdout,r4 ;02
mov #c$pmtr+0,r0
br prf002
¤
fprint::
jsr r5,csv$
mov #$$putc,r1
br prf001
¤
sprint::
jsr r5,csv$
mov #putsc,r1
¤
prf001:
mov c$pmtr+0(r5),r4
mov #c$pmtr+2,r0
¤
prf002:
sub #STACK,sp ;Get stack area
mov r1,FUNC(r5) ;Save output func. ;01-
add r5,r0
mov (r0)+,r3 ;r3 -> format
mov r0,ARGP(r5) ;ARGP(r5) -> arg's.
¤
;
; Get next character from the
; format string.
; If not a '%' just send it to the
; output.
;
¤
¤
prf01: movb (r3)+,r0
bne 25$ ;01+
jmp prf03
25$: ;01-
¤
cmp r0,#'%
beq 30$
call @FUNC(r5)
br prf01
¤
;
; Get widths and flags.
;
¤
30$:
clr LJUST(r5)
clr WIDE(r5)
mov #-1,PREC(r5)
mov #' ,FILL(r5)
¤
movb (r3)+,r0
cmp r0,#'-
bne 40$
inc LJUST(r5)
movb (r3)+,r0
¤
40$:
cmp r0,#'0
bne 50$
mov r0,FILL(r5)
movb (r3)+,r0
¤
50$:
call num
mov r1,WIDE(r5)
¤
cmp r0,#'.
bne 60$
movb (r3)+,r0
call num
mov r1,PREC(r5)
¤
;
; %r Remote format
;
¤
60$:
cmp r0,#'r
bne 70$
mov @ARGP(r5),ARGP(r5)
mov @ARGP(r5),r3
add #2,ARGP(r5)
br prf01
¤
;
; %e, %f, %g Floating point
;
; All of the dirty work is done
; by '$$dtoa'.
; The PREC is set to -1 because these
; items use the PREC field in an
; unstandard way.
;
¤
70$:
mov r5,r2
add #BUF,r2
¤
cmp r0,#'e
beq 80$
cmp r0,#'f
beq 80$
cmp r0,#'g
bne 90$
¤
80$:
mov ARGP(r5),r1
add #10,r1
mov r1,ARGP(r5)
mov -(r1),-(sp)
mov -(r1),-(sp)
mov -(r1),-(sp)
mov -(r1),-(sp)
mov PREC(r5),-(sp)
mov WIDE(r5),-(sp)
mov r0,-(sp)
mov r2,-(sp)
call $$dtoa
add #20,sp
mov #-1,PREC(r5)
br prf02
¤
;
; Get the data. If there is an 'l' in
; the format copy a long to HORD and
; LORD. Otherwise copy the integer to
; LORD and sign extend if %d.
;
¤
90$:
mov ARGP(r5),OLDP(r5)
mov @ARGP(r5),r1
add #2,ARGP(r5)
¤
cmp r0,#'l
bne 100$
;
; %l Long integer
;
mov r1,HORD(r5)
mov @ARGP(r5),LORD(r5)
add #2,ARGP(r5)
movb (r3)+,r0
br 120$
¤
100$:
cmp r0,#'d
beq 110$
mov r1,LORD(r5)
clr HORD(r5)
br 120$
¤
110$:
clr HORD(r5)
mov r1,LORD(r5)
bpl 120$
com HORD(r5)
¤
;
; %c Character
;
¤
120$:
cmp r0,#'c
bne 130$
mov r5,r2
add #LORD,r2
clrb LORD+1(r5)
br prf02
¤
;
; %s String
;
; If pointer is 0, print {Null}
;
¤
130$:
cmp r0,#'s
bne 140$
mov LORD(r5),r2
bne prf02
mov #null,r2
br prf02
¤
;
; %d, %o, %u, %x, %X Integer conversion
;
; Only %d gets integers sign extended.
; All done with common routine.
;
¤
140$:
cmp r0,#'d
beq 150$
cmp r0,#'o
beq 150$
cmp r0,#'u
beq 150$
cmp r0,#'x
beq 150$
cmp r0,#'X
bne 160$
¤
150$:
mov LORD(r5),-(sp)
mov HORD(r5),-(sp)
mov r0,-(sp)
mov r2,-(sp)
call $$ltoa
add #10,sp
br prf02
¤
;
; None of the above.
; Restore ARGP so an argument is not
; eaten.
;
¤
160$:
mov OLDP(r5),ARGP(r5)
call @FUNC(r5)
jmp prf01 ;01
¤
;
; Send out the null terminated ascii
; string pointed to by r2.
; Inserted any required fills and
; pads.
;
¤
prf02: mov r2,r1
¤
170$:
tstb (r1)+
bne 170$
dec r1
sub r2,r1
¤
tst PREC(r5)
bmi 180$
cmp PREC(r5),r1
bhis 180$
mov PREC(r5),r1
¤
180$:
mov r1,PREC(r5)
¤
tst LJUST(r5)
bne 190$
call fills
¤
190$:
mov PREC(r5),r1
¤
200$:
dec r1
bmi 210$
movb (r2)+,r0
call @FUNC(r5)
br 200$
¤
210$:
tst LJUST(r5)
beq 215$ ;01
call fills
¤
215$: ;01
jmp prf01 ;01
¤
;
; All done.
; If this is a call to sprintf append
; the null byte.
;
¤
prf03: cmp FUNC(r5),#putsc
bne 220$
clrb (r4)
¤
220$:
jmp cret$
¤
;
; This is the putchar routine used by
; sprintf.
; On entry, r0 is the character and
; r4 is the string pointer.
;
¤
putsc: movb r0,(r4)+
return
¤
;
; Output WIDE - PREC copies of the
; FILL character.
;
¤
fills: mov WIDE(r5),r1
sub PREC(r5),r1
ble 240$
¤
mov FILL(r5),r0
¤
230$:
call @FUNC(r5)
dec r1
bne 230$
¤
240$:
return
¤
;
; Read in a field width.
; The first character of the width is
; in r0.
; The width is returned in r1.
; If the width specifier is '?' then the
; width is obtained from the args.
;
¤
num: cmp r0,#'?
bne 250$
mov @ARGP(r5),r1
add #2,ARGP(r5)
movb (r3)+,r0
br 270$
¤
250$:
clr r1
¤
260$:
cmp r0,#'0
blo 270$
cmp r0,#'9
bhi 270$
¤
asl r1
mov r1,-(sp)
asl r1
asl r1
add (sp)+,r1
¤
add r0,r1
sub #'0,r1
movb (r3)+,r0
br 260$
¤
270$:
return
¤
.end
-
? Patron - 10.02.2011 19:08
.title $$ltoa Convert long to ascii
¤
;
; The information in this document is subject to change
; without notice and should not be construed as a commitment
; by Digital Equipment Corporation or by DECUS.
;
; Neither Digital Equipment Corporation, DECUS, nor the authors
; assume any responsibility for the use or reliability of this
; document or the described software.
;
; Copyright (C) 1980, DECUS
;
;
; General permission to copy or modify, but not for profit, is
; hereby granted, provided that the above copyright notice is
; included and reference made to the fact that reproduction
; privileges were granted by DECUS.
;
.ident /000001/
¤
;+
;
; Internal
;
; Usage
;
; $$ltoa(buff, radix, value);
; char *buff; /* Where it goes */
; int radix; /* Conversion radix */
; long value; /* What to convert */
;
; Description
;
; Called by printf to convert a long integer from binary
; to Ascii, storing the result in buffer. The radix argument
; determines the conversion:
;
; d Signed decimal
; o Octal
; u Unsigned decimal
; X Hex (10-15 = A-F)
; x Hex (10-15 = a-f)
;
; Bugs
;
;-
;
; Edit history
; 000001 05-Mar-80 MM Initial edit
;
.psect .prog.
;
; Double precision power of
; ten table. Used by the decimal
; conversion.
;
¤
tab: .word 052013, 162000
.word 035632, 145000
.word 002765, 160400
.word 000230, 113200
.word 000017, 041100
.word 000001, 103240
.word 000000, 023420
.word 000000, 001750
.word 000000, 000144
.word 000000, 000012
tabe:
¤
$$ltoa::
jsr r5,csv$
mov c$pmtr+0(r5),r4
mov c$pmtr+4(r5),r2
mov c$pmtr+6(r5),r3
clr -(sp)
cmp c$pmtr+2(r5),#'d
beq 70$
cmp c$pmtr+2(r5),#'u
beq 80$
¤
;
; Octal.
; Hexadecimal.
;
¤
mov #8.,r1
cmp c$pmtr+2(r5),#'o
bne 10$
mov #11.,r1
clr r0
br 20$
¤
10$:
clr r0
asl r3
rol r2
rol r0
¤
20$:
asl r3
rol r2
rol r0
asl r3
rol r2
rol r0
¤
cmp c$pmtr+2(r5),#'o
beq 30$
asl r3
rol r2
rol r0
¤
30$:
cmp r1,#1
beq 40$
tst r0
bne 40$
tst (sp)
beq 60$
¤
40$:
inc (sp)
add #'0,r0
cmp r0,#'9
blos 50$
add #'A-'0-10.,r0
cmp c$pmtr+2(r5),#'X
beq 50$
add #'a-'A,r0
¤
50$:
movb r0,(r4)+
¤
60$:
dec r1
bne 10$
br 150$
¤
;
; Decimal.
; Unsigned.
;
¤
70$:
tst r2
bpl 80$
movb #'-,(r4)+
neg r2
neg r3
sbc r2
¤
80$:
mov #tab,r1
¤
90$:
clr r0
¤
100$:
cmp r2,(r1)
blo 120$
bhi 110$
cmp r3,2(r1)
blo 120$
¤
110$:
sub (r1),r2
sub 2(r1),r3
sbc r2
inc r0
br 100$
¤
120$:
tst r0
bne 130$
tst (sp)
beq 140$
¤
130$:
inc (sp)
add #'0,r0
movb r0,(r4)+
¤
140$:
add #4,r1
cmp r1,#tabe
blo 90$
¤
add #'0,r3
movb r3,(r4)+
¤
150$:
clrb (r4)
jmp cret$
.end
-
? Patron - 10.02.2011 19:11
.title $$dtoa Convert double to Ascii
¤
;
; The information in this document is subject to change
; without notice and should not be construed as a commitment
; by Digital Equipment Corporation or by DECUS.
;
; Neither Digital Equipment Corporation, DECUS, nor the authors
; assume any responsibility for the use or reliability of this
; document or the described software.
;
; Copyright (C) 1980, DECUS
;
;
; General permission to copy or modify, but not for profit, is
; hereby granted, provided that the above copyright notice is
; included and reference made to the fact that reproduction
; privileges were granted by DECUS.
;
.ident /000001/
;
;+
;
; Internal
;
; Usage
;
; $$dtoa(buff, conv, field, dplace, value)
; char *buff; /* Where it goes */
; char conv; /* Conversion type */
; int field; /* Maximum field width */
; int dplace; /* Decimal part width */
; double value; /* What to convert */
;
; char *
; $$ecvt(negfl, scale, field, dplace, value)
; int *negfl; /* 0 if +, 1 if - value */
; int *scale; /* Set to scale factor */
; int field; /* Maximum field width */
; int dplace; /* Decimal part width */
; double value; /* What to convert */
;
; char *
; $$fcvt(negfl, scale, field, dplace, value)
; int *negfl; /* 0 if +, 1 if - value */
; int *scale; /* Set to scale factor */
; int field; /* Maximum field width */
; int dplace; /* Decimal part width */
; double value; /* What to convert */
;
; Description
;
; $$dtoa() is called by printf to convert a double-precision value
; to Ascii. The text is written to buff[]. Field and dplace are
; the conversion parameters "f" and "d" in the format string "%f.df"
; Conv is 'e', 'f', or 'g' to define the format. Note:
; the conversion character must be in lower-case.
;
; $$ecvt() and $$fcvt() perform the conversions, returning a pointer
; to an internal character buffer. On return, negfl will be
; non-zero if the value was less than zero, and scale will be set
; to the scaling factor.
;
; Diagnostics
;
; Bugs
;
; "%g" does not exist yet. It is equivalent to "%f".
;
; The code has not been tested as there is no fpu support yet.
;
;-
;
; Edit history
; 000001 28-Apr-80 MM Initial attempt
;
;
; Locate the items
;
BUFFER = 0
CONV = 2
FIELD = 4
DPLACE = 6
VALUE = 10
¤
.psect .prog.
¤
$$dtoa::
.if ne 1
CRASH ; NOT YET
.iff
jsr r5,csv$ ; Establish linkage
call fcvt ; Do the conversion
;
; Return:
; r0 -> internal buffer
; r1 := non-zero if negative value
; r2 := scale factor
;
mov C$PMTR+BUFFER(r5),r3 ; r3 -> output buffer
tst r1 ; Negative value?
beq 20$ ; Br if positive
movb #'-,(r3)+ ; Negative, say so
20$:
cmpb C$PMTR+CONV(r5),#'e ; Exp. format?
beq eout ; Br if so.
;
; Decimal output, do the part before the decimal point
;
dout: mov r2,r1 ; r1 := scale factor
bgt 10$ ; Br if something before the '.'
movb #'0,(r3)+ ; Nothing there, 0.123 style
br 20$ ; Continue main sequence
;
10$:
jsr pc,movdig ; Do a digit
dec r1 ; Count it
bne 10$ ; Loop till there gone.
;
; Do the decimal point and whatever's left
;
20$:
mov C$PMTR+DPLACE(r5),r1 ; How many decimal digits?
ble exit ; Br if none wanted
movb #'.,(r3)+ ; Output the decimal point
neg r2 ; Check the scale factor
ble 40$ ; Br if no leading zero's
;
; Output leading zero's before the decimal fraction
;
30$:
movb #'0,(r3)+ ; Output a zero
dec r1 ; Count it
ble exit ; Exit if no more
dec r2 ; Count the scale
bne 30$ ; Maybe do another zero
;
; Now, for the fraction part
;
40$:
call movdig ; Output a digit
dec r1 ; count it as part of the field
bne 40$ ; keep put the good work.
br exit ; No more.
;
; Output an exponential format
;
eout:
call movdig ; Leading digit goes first
movb #'.,(r3)+ ; Then a decimal point
mov C$PMTR+DPLACE,r1 ; How many digits
dec r1 ; In %f.we, w has the total
ble 20$ ; number of digits.
;
; Output some digits from the fraction
;
10$:
call movdig ; Output one digit
dec r1 ; Count it as gone
bne 10$ ; loop for them all
¤
20$:
movb #'e,(r3)+ ; Fraction done, now for the
dec r2 ; scale.
mov r2,r1 ; Get the scale
bge 30$ ; Positive scale?
movb #'-,(r3)+ ; Nope, output a negative
neg r1 ; Signal so
br 40$ ; and rejoin main sequence
;
30$:
movb #'+,(r3)+ ; Positive scale
;
40$:
mov #10.,(sp) ; Divide scale factor
mov r1,-(sp) ; by ten
call div$i ; use library divider
tst (sp)+ ; Clear the stack
add #'0,r0 ; Make ten's place an ascii
movb r0,(r3)+ ; byte and output it
add #'0,r1 ; Make unit's place an ascii
movb r1,(r3)+ ; byte and output it
;
exit:
clrb (r3) ; Normal exit, terminate output
jmp cret$ ; and exit.
;
; Move out one digit, calling sequence:
; r0 -> input buffer
; r3 -> output buffer
; Note: if the input buffer is empty (i.e., (r0) = 0), '0' is output.
;
; Return, r0, r3 updated.
;
movdig:
movb (r0)+,(r3)+ ; Output the byte
bne 10$ ; Br if not empty
dec r0 ; Urk, backup input pointer
movb #'0,-1(r3) ; and fix output.
;
10$:
rts pc ; Exit
;
; $$fcvt() and $$ecvt call fcvt and return a pointer to the internal
; buffer.
;
¤
$$fcvt::
jsr r5,csv$ ; Establish linkage
mov C$PMTR+CONV(r5),(sp) ; Save -> scale
mov #'f,C$PMTR+CONV(r5) ; Fake a %f call
br ecvt1 ; Continue
;
$$ecvt::
jsr r5,csv$ ; Establish linkage
mov C$PMTR+CONV(r5),(sp) ; Save -> scale
mov #'e,C$PMTR+CONV(r5) ; Fake a %e call
¤
ecvt1:
mov r1,@C$PMTR+0(r5) ; Return neg. flag
mov r2,@(sp)+ ; Return scale factor
jmp cret$ ; That's all.
;
; Perform the dirty work of converting the arg. to ascii. On return:
;
; r0 -> local buffer with Ascii digit string
; r1 := zero if value is positive, 1 if negative
; r2 := scale factor (eNN)
;
; r3-r4 are trashed
;
;
.psect .data.
saver1: .blkw 1 ; Save r1 for div10
buf: .blkb 40. ; Local buffer for fcvt
.byte 0 ; Terminate a full buffer
.even
¤
.psect .prog.
fcvt:
clr -(sp) ; Get a temp (digit counter)
tst C$PMTR+FIELD(r5) ; Field size given
bne 10$ ; Br if so
mov #6.,C$PMTR+FIELD(r5) ; No, use 6
10$:
mov C$PMTR+VALUE+6(r5),r3 ; Load floating
mov C$PMTR+VALUE+4(r5),r2 ; argument into
mov C$PMTR+VALUE+2(r5),r1 ; r0 .. r3
mov C$PMTR+VALUE+0(r5),r0 ; r0 has exponent part
beq scaled ; Don't scale if its zero
bic #177600,r0 ; Clear out the exponent
bis #200,r0 ; Light the hidden bit
call norm ; Normalize the fraction
mov C$PMTR+VALUE+0(r5),r4 ; Get the exponent part
asl r4 ; Just want the
clrb r4 ; Exponent part
swab r4 ;
sub #128.,r4 ; Normalize excess 128 format
bgt 30$ ; Continue if abs(VALUE) >= 1.0
¤
20$:
call mul10 ; Multiply the fraction by
dec (sp) ; ten to normalize the exponent
call norm ; Shift around until
tst r4 ; The exponent becomes
ble 20$ ; greater than zero.
;
30$:
call div10 ;
inc (sp) ;
call norm ;
tst r4 ;
bgt 30$
beq scaled
;
40$:
call right
inc r4
bne 40$
;
; The number is scaled, output it
;
scaled: mov #buf,r4 ; r4 -> local data buffer
;
10$:
call mul10 ; Multiply r0-r3 by 10
mov r0,-(sp) ; save high-order value
asr r0 ; Find the decimal byte
asr r0 ;
asr r0 ;
swab r0 ;
bic #177760,r0 ; Mask out the digit
add #'0,r0 ; Make it ascii
movb r0,(r4)+ ; and output it
mov (sp)+,r0 ; Recover high-order value
bic #170000,r0 ; Clean out the digit
cmp r4,#buftop ; Gone far enough already?
blo 10$ ; No, keep on digitizing
;
; More or less done, locate the end of the output and round off
;
mov #buf,r0 ; Yes, r0 -> local buffer
add C$PMTR+FIELD(r5),r0 ; r0 -> local buffer end
cmpb C$PMTR+CONV(r5),#e ; Exp format?
bne 20$ ; Nope
add (sp),r0 ; Tack on scale factor
cmp r0,#buftop ; If we've gone outside the buffer
bhis done ; we're done
cmp r0,#buf ; Check both ends of the buffer
blo done ; for doneness
movb (r0),r3 ; do some rounding
add #5.,r3 ; Make it a nice round number
movb r3,(r0) ; Shove it back
;
; Carry out more rounding
;
20$:
cmpb (r0),#'9 ; Overflow?
ble done ; no, finis
movb #'0,(r0) ; yep, nullify it
cmp r0,#buf ; at the end?
blos 30$ ; yep, exit
incb -(r0) ; nope, try the next
br 20$ ; decimal place
;
30$:
movb #'1,(r0) ; Overflowed everywhere
inc (sp) ; Step the scale factor
;
done:
mov C$PMTR+FIELD(r5),r0 ; Field width
cmpb C$PMTR+CONV(r5),#e ; Exp format?
bne 10$ ; nope
add (sp),r0 ; yep, fix
;
10$:
tst r0 ; where's the decimal point
blt 20$ ; nowhere interesting
cmp r0,#buftop-buf ; is it too far?
bge 20$ ; yep
clrb buf(r0) ; Very good, terminate the string.
;
20$: mov (sp)+,r2 ; Return scale factor
clr r1 ; Assume positive
tst C$PMTR+VALUE(r5) ; Really positive?
bpl 30$ ; Br if so.
inc r1 ; negative.
;
30$:
mov #buf,r0 ; r0 -> buffer
rts pc ; and exit.
;
;
; Normalize the very long integer in r0-r3
;
norm:
;
10$:
cmp r0,#004000
bhis 20$
call left
dec r4
br 10$
;
20$: cmp r0,#010000
blo 30$
call right
inc r4
br 20$
;
30$: rts pc
;
;
; Divide the very long integer by 10
;
div10:
mov r1,saver1
mov r0,r1
clr r0
jsr r5,divide ; r0,r1 / 10.
.word 10.
mov r0,-(sp)
mov r1,r0
mov saver1,r1
jsr r5,divide
.word 20.
mov r0,-(sp)
mov r1,r0
mov r2,r1
jsr r5,divide
.word 40.
mov r0,r2
mov r1,r0
mov r3,r1
jsr r5,divide
.word 80.
mov r0,r3
;
; Set r0 to r1 / 10 (rounded)
;
clr r0
jsr r5,divide
.word 5.
inc r0
asr r0
;
mov (sp)+,r1
asl r3
asl r3 ; ashc #2, r2
rol r2 ;
asl r3 ;
rol r2 ;
rol r1
add r0,r3
adc r2
adc r1
mov (sp)+,r0
adc r0
rts pc
;
; divide r0,r1 by (r5), algorithm from Ekhouse and Morris.
;
divide:
mov r4,-(sp) ; Get a temp.
mov #16.,r4 ; Doing 16 bits
¤
10$: asl r1 ; Long shift dividend
rol r0 ;
sub (r5),r0 ; dividend > divisor
bmi 30$ ; nope
bis #1,r1 ; yes, increase quotient
br 30$ ; continue at counter
;
20$: asl r1 ; Long shift dividend
rol r0 ;
add (r5),r0 ; Still too little?
bmi 30$ ; yep
bis #1,r1 ; nope, increase quotient
dec r4 ; count the cycle
bne 20$ ; return if more
br 40$ ; done, exit.
;
30$: dec r4 ; count the cycle
bne 10$ ; return if more
;
40$: tst r0 ; final fixup of remainder
bge 50$ ; none needed
add (r5),r0 ; fixed.
;
50$: tst (r5)+ ; skip over arg. for exit
mov (sp)+,r4 ; restore temp.
rts r5 ; and exit.
;
;
; Multiply r0 .. r3 by ten
;
mul10:
call left ; arg * 2
mov r0,-(sp) ; save partial result
mov r1,-(sp) ;
mov r2,-(sp) ;
mov r3,-(sp) ;
call left ; arg * 4
call left ; arg * 8
add (sp)+,r3 ; (arg * 10) = (arg * 8) + (arg * 2)
adc r2
adc r1
adc r0
add (sp)+,r2
adc r1
adc r0
add (sp)+,r1
adc r0
add (sp)+,r0
rts pc
;
; Left shift r0 .. r3
;
left:
asl r3
rol r2
rol r1
rol r0
rts pc
;
; Right shiift r0 .. r3
;
right:
clc
ror r0
ror r1
ror r2
ror r3
rts pc
;
¤
.endc
.end
-
? Patron - 10.02.2011 19:22
.title csv$ C register save and restore
¤
;
; The information in this document is subject to change
; without notice and should not be construed as a commitment
; by Digital Equipment Corporation or by DECUS.
;
; Neither Digital Equipment Corporation, DECUS, nor the authors
; assume any responsibility for the use or reliability of this
; document or the described software.
;
; Copyright (C) 1980, DECUS
;
;
; General permission to copy or modify, but not for profit, is
; hereby granted, provided that the above copyright notice is
; included and reference made to the fact that reproduction
; privileges were granted by DECUS.
;
.ident /00005/
;
;+
;
; Internal
;
; Usage
;
; jsr r5,csv$
; ...
; jmp cret$
;
; Description
;
; C program Run-time Environment
;
; Each C subroutine starts with a call to CSV$ and exits by
; jumping to CRET$. Upon exit, the stack need not be equal
; to its value on entrance.
;
; During the execution of all C subroutines, register R5
; points to the current "environment." Within a subroutine,
; it appears as follows:
;
; _______________
; | |
; SP -> | 1st loc. var. | -10(R5) C$AUTO-2(R5)
; |_______________|
; | |
; | Saved R2 | -6(R5)
; |_______________|
; | |
; | Saved R3 | -4(R5)
; |_______________|
; | |
; | Saved R4 | -2(R5)
; |_______________|
; | |
; R5 -> | Saved R5 |
; |_______________|
; | |
; | Return add. | +2(R5)
; |_______________|
; | |
; | First arg. | +4(R5) C$PMTR+0(R5)
; |_______________|
; | |
; | Second arg. | +6(R5) C$PMTR+2(R5)
; |_______________|
;
; Within a subroutine, Registers R0-R4 and the top of the
; stack, (sp) are available for use. Registers R0 and R1
; are not preserved by subroutines and may be used to pass
; a return value.
;
; R5 must not be modified by a subroutine. All variable
; addressing must be done by offsets to R5. Subroutine
; arguments must be accessed by reference to C$PMTR.
; Subroutine local variables must be accessed by reference
; to C$AUTO. This permits modification of calling sequences
; without rewriting all subroutines.
;
; CSV$ refers to global symbol $$main to call the run-time startup
; program from the (RSX) library.
;
; Bugs
;
;-
;
; Edit history
; 01 JMT Original
; 02 MM Documentation
; 03 MM Fix bug in CRET$ and define C$PMTR, C$AUTO
; 04 MM Bum one word and name $$main
; 05 MM C$PMTR/C$AUTO are now defined in RSX.MAC and RT11.MAC
¤
;
; If C$PMTR/C$AUTO are undefined, just define them ;05+
;
.iif ndf C$PMTR C$PMTR = 4 ;formal[n] @ c$pmtr+<n*2>(r5)
.iif ndf C$AUTO C$AUTO = -6 ;local[n] @ c$auto-<n*2>(r5)
.globl C$PMTR, C$AUTO
.iif ne C$PMTR-4 .error Bad definition of C$PMTR
.iif ne C$AUTO+6 .error Bad definition of C$AUTO
;
; By defining C$PMTR and C$AUTO as local symbols, the task
; builder need not do so much work ;05-
¤
.GLOBL $$MAIN ;Call start from the library ;04
¤
.PSECT .PROG.
;
; save R4-R2 and make a one-word temp slot on the stack.
;
CSV$::
MOV R5, R0
MOV SP, R5
MOV R4, -(SP)
MOV R3, -(SP)
MOV R2, -(SP)
JSR PC,(R0) ;TST -(SP) JMP (R0) ;04
;
; pop R2-R4 and restore stack linkage registers.
;
CRET$::
MOV R5, R2 ;03 +
MOV -(R2), R4
MOV -(R2), R3
MOV -(R2), R2 ;03 -
MOV R5, SP
MOV (SP)+, R5
RTS PC
.END
-
? anonymous - 10.02.2011 21:48
Выкладывайте лучше ссылки, а сами файлы можно положить, если негде, например у М. Багаева, на http://forum.maxiol.com/index.php?showforum=68 есть возможность загрузки файлов.
- << Форум