Skip to content

Instantly share code, notes, and snippets.

@mdchaney
Created September 26, 2014 16:06
Show Gist options
  • Save mdchaney/4e2f3c35c20915fe9716 to your computer and use it in GitHub Desktop.
Save mdchaney/4e2f3c35c20915fe9716 to your computer and use it in GitHub Desktop.
.Title EFinder Program to evaluate e
.Ident 'V03-02'
.Show MEB
;The purpose of this program will be to find e out to the
;specified number of decimal places. The idea here will be to use the
;definition:
;
; 1 1 1 1 1 1 1
; e = - + - + - + - + - + - + - + ...
; 0! 1! 2! 3! 4! 5! 6!
;
;The user will be prompted for the number of digits.
;
;This particular version will time the whole thing. At 8:00 AM, the priority
;will be dropped to 0. At 11:00 PM, it will raise to 2.
;
;The main difference between this version and others is that this one will use
;a radix 1000000000 representation of the numbers. Therefore, cutting in half
;the amount of space needed for storage of digits.
.Library 'Sys$Library:Lib.MLb;'
.Link 'Sys$System:Sys.STb;'
.Psect Data,Long
$PHdDef
Starttime: .Long 0
IOTime: .Long 0
EndTime: .Long 0
TotalTime: .Quad 0
ExtraTime: .Quad 0
CompTime: .Ascid /The computing time was: /
DoIOTime: .Ascid /The IO time was: /
EndOfThese=.
TotDes: .Long 18
.Address <DoIOTime-18>
IODes: .Long 18
.Address <EndOfThese-18>
.NoShow MEB
OutFAB: $FAB Fnm=<$Disk28:[MDChaney]E.TXT;>,mrs=132,DEQ=1,rat=CR
OutRAB: $RAB FAB=OutFAB,Rsz=132,RBf=OutBuf
.Show MEB
OutBuf: .Byte 32[132]
EndBuf=.
MiniDes:.Long 9
.Address MiniBuf
MiniBuf:.BlkB 9
Line1: .ascii /e approximation follows, accurate to /
NumberODigits: .blkb 10
.ascii / digits: /
EndLine1:
Prompt: .Ascid /How many digits of e would you like to have? > /
Inline: .Ascid / /
L: .Long 0
RealTime:.Quad 0
RealATime:.Ascii / /
Sometime: .Ascii / /
RDes: .Long 23
.Address RealATime
Tim8: .Ascii /08:00:00.00/
Tim11: .Ascii /23:00:00.00/
Addresses: .Quad 0
NAdd: .Address EF
.Address Bye
MesDes: .Long 256
.Address BigBuf
BigBuf: .BlkB 256
.Psect Code,Page
.Entry EF,^M<>
PushaW InLine ;The length
PushaQ Prompt ;The Prompt
PushaQ InLine ;The Descriptor for Inline
CallS #3,G^Lib$Get_Input ;Get the input
PushL #4 ;Output will Occupy 4 bytes
PushAL L ;Put it here
PushAQ InLine ;The Ascii Equiv
CallS #3,G^OTS$CVT_TI_L ;do the conversion
BLBS R0,10$
PushL R0
CallS #1,G^Lib$Signal
10$: MovC3 #10,@<4+InLine>,NumberODigits ;move the ascii
DivL3 S^#9,L,R9 ;get # of longwords
IncL R9 ;Put the length in R9
AShL S^#2,R9,R9 ;and the length in bytes
MovL SP,<Addresses+4> ;set up the addresses
SubL2 R9,SP ;this will be a
SubL2 S^#4,SP ;put in a safety longword
MovL SP,R10 ;put a into R10
SubL2 R9,SP ;this will be e
SubL2 S^#4,SP ;another safety longword
MovL SP,R11 ;put e into r11
MovL SP,Addresses ;and the beginning address
AShL S^#1,R9,R1 ;get the length of both arrays
AddL2 S^#8,R1 ;add in the protections
BiCL3 #^XFFFF0000,R1,R6 ;R6=leftover
AShL #-16,R1,R7 ;R7=number of big blocks
MovL SP,R3 ;The Base address of the arrays
MovC5 #0,(R0),#0,R6,(R3) ;clear out the start
TstL R7 ;check for big blocks
BEql 20$ ;branch if none
15$: MovC5 #0,(R0),#0,#65535,(R3) ;clear out a block
ClrB (R3)+ ;make that even
SOBGtr R7,15$ ;and loop
20$: BrW Main ;skip priority change
$AscTim_S- ;get the ascii time
TimBuf=RDes ;where to put it
CmpB S^#^A/1/,SomeTime ;check this
BGEq StartLow ;if it is >1, start with low
CmpB S^#^A/8/,SomeTime+1 ;check second digit
BGEq StartLow ;if it is >8, start low
;here, it's <08
MovC3 #11,Tim8,SomeTime ;make it 8 in the morning
ClrB Flag ;clear the flag
$BinTim_S- ;make it binary
TimBuf=RDes,- ;the ascii
TimAdr=NextTime ;the binary
$SeTimr_S- ;set the timer
DayTim=NextTime,- ;the time
ASTAdr=MyAST ;the AST
BrB Main ;go to main
StartLow: ;here, it's >=08
MovC3 #11,Tim11,SomeTime ;make it 11 at night
MovB S^#1,Flag ;set the flag
$BinTim_S- ;make it binary
TimBuf=RDes,- ;the ascii
TimAdr=NextTime ;the binary
$SeTimr_S- ;set the timer
DayTim=NextTime,- ;the time
ASTAdr=MyAST ;the AST
$SetPri_S Pri=NoPri,PrvPri=OldPri ;reset the priority
Main: MovL CTL$GL_PHD,R12 ;get the P1 window to process header
MovL PHD$L_CPUTIM(R12),StartTime ;this is the starting time
$LkWSet_S InAdr=NAdd,RetAdr=NAdd ;lock code into working set
$LkWSet_S InAdr=Addresses,RetAdr=Addresses ;lock arrays in working set
CvtBL I^#-4,AP ;put -4 into AP
MovL #100000000,(R10) ;set up the arrays
MovL #200000000,(R11) ;digit in e (Kickstart)
MovL #1000000000,R0 ;put a billion in R0
MovL #999999999,R4 ;R4 is the maximum before carry
ClrL R7 ;first zero level
MovL S^#2,R8 ;first divisor
SubL2 S^#4,R9 ;less length
.Align Long,1 ;align on longword boundary, with NOP's
Another:
AddL3 R10,R7,R6 ;get address of z in R6
AddL3 R10,R9,R5 ;address of top element
ClrQ R1 ;clear accumulator
.Align Long,1 ;align with NOP's
Divide: AddL2 (R6),R1 ;add into accumulator
AdWC S^#0,R2 ;add carry bit to R2
EDiv R8,R1,(R6),R1 ;divide accum by c, (R6)=Quo,R1=Remainder
EMul R0,R1,S^#0,R1 ;multiply Remainder by 1E9 for shift
ACBL R5,S^#4,R6,Divide ;loop
AddL3 R10,R7,R3 ;R3 will point to the current zero level
.Align Long,1 ;align with NOP's
UpDateZ:TstL (R3)+ ;check to move zero level
BNEq On ;branch if found
ACBL R9,S^#4,R7,UpDateZ ;loop, incrementing z
BrB OuttaHere ;leave, we're done
On: AddL3 R9,R11,R6 ;bottom of array e
AddL3 R9,R10,R5 ;bottom of array a
AddL2 S^#4,R5 ;go one past the bottom
AddL3 R7,R11,R3 ;zero level address at array e
.Align Long,1 ;align with NOP's
AdLoop: AddL2 -(R5),(R6) ;add the two together
CmpL (R6),R4 ;check for carry
BLEq Redo ;None, loop
IncL -4(R6) ;Perform carry
SubL2 R0,(R6) ;take carry from here
Redo: ACBL R3,AP,R6,AdLoop ;loop to zero level
.Align Long,1 ;align with NOP's
Carry: CmpL (R6),R4 ;look for more carry
BLEq NoCarry ;None? go on
IncL -4(R6) ;Perform carry
SubL2 R0,(R6) ;take carry from here
ACBL R11,AP,R6,Carry ;loop to top
NoCarry:IncL R8
Brb Another
Outtahere:
MovL CTL$GL_PHD,R12 ;get the P1 window to process header
MovL PHD$L_CPUTIM(R12),IOTime ;this is the starting time for IO
$Create FAB=OutFAB ;create the output file
BLBS R0,10$ ;check for error
BrW Bye
10$: $Connect RAB=OutRAB ;connect the RAB with the FAB
BLBS R0,20$ ;check for error
BrW Bye
20$: MovaB Line1,<OutRAB+RAB$L_RBF> ;print this to file
MovW #<EndLine1-Line1>,<OutRAB+RAB$W_RSZ>
$Put RAB=OutRAB ;print out top line
BlBS R0,21$ ;go here on success
BrW Bye ;leave with error
21$: MovW #132,<OutRAB+RAB$W_RSz> ;new record size
MovAB OutBuf,<OutRAB+RAB$L_RBf> ;new buffer
AddL3 R9,R11,R7 ;end of the array
MovL R11,R6 ;start of the array
MovW #^A/2./,OutBuf ;beginning of e
PushAQ MiniDes ;the descriptor
PushL R6 ;where to get it
CallS S^#2,Convert ;convert to ascii
MovC3 S^#8,<MiniBuf+1>,<OutBuf+2> ;move in the characters
MovL R3,R2 ;and get the address in the string
AddL2 S^#4,R6 ;go to the next Longword
PLoop: PushAQ MiniDes ;the descriptor
PushL R6 ;and where to get it
CallS S^#2,Convert ;convert these!
MovAB MiniBuf,R3 ;where to get ascii
MovL S^#9,R5 ;how many ascii's
10$: MovB (R3)+,(R2)+ ;put in the character
CmpL R2,#EndBuf ;see if we are to the end
BNEq 20$ ;if not, go on
$Put RAB=OutRAB ;put the record
BLBS R0,15$ ;go on with success
BrB Bye ;leave with error
15$: PushR #^M<R3,R5> ;save working registers
MovC5 S^#0,(R0),S^#^A/ /,#132,OutBuf ;blank this out
PopR #^M<R3,R5> ;and restore these two
MovAB OutBuf,R2 ;start back at beginning
20$: SOBGtr R5,10$ ;loop with characters
ACBL R7,S^#4,R6,PLoop ;next longword
CmpB OutBuf,S^#^A/ / ;see if line is blank
BEql Bye ;leave if so
$Put RAB=OutRAB ;put the record
Bye: MovL PHD$L_CPUTIM(R12),EndTime ;this is the ending time
BLBS R0,10$ ;go here if OK
$GetMsg_S BufAdr=MesDes,MsgLen=MesDes,MsgId=R0
PushAQ MesDes ;print it
CallS S^#1,G^Lib$Put_Output ;call library routine
10$: $ULWSet_S InAdr=Addresses ;unlock all those pages
$ULWSet_S InAdr=NAdd ;lock these mothers
SubL3 StartTime,IOTime,ExtraTime ;Get the time for initial execution
SubL3 IOTime,EndTime,TotalTime ;get the IO total time
EMul ExtraTime,#-100000,#0,ExtraTime ;multiply by 100000 to get quad
EMul TotalTime,#-100000,#0,TotalTime ;get quad format for this
$AscTim_S TimBuf=TotDes,- ;where to put it
TimLen=TotDes,- ;the length
TimAdr=ExtraTime ;where to get it from
$AscTim_S TimBuf=IODes,- ;where to put it
TimLen=IODes,- ;the length
TimAdr=TotalTime ;where to get it from
PushAQ CompTime ;we'll print this
CallS #1,G^Lib$Put_Output ;put the output
PushAQ DoIOTime ;print this
CallS #1,G^Lib$Put_Output ;put the output
MovL FP,SP
PushL R0
$Close FAB=OutFAB
CallS #1,G^Sys$Exit
;This is the Subroutine Convert. It is passed 2 arguments, the Longword and
;the string descriptor.
.Entry Convert,^M<R2,R3,R4,R5>
MovL @4(AP),R0 ;get the longword
MovL 8(AP),R3 ;address of string descriptor
AddL3 (R3),4(R3),R4 ;one byte past string end
MovL S^#9,R5 ;the loop counter
ClrL R1 ;top half of quadword
10$: EDiv S^#10,R0,R0,R2 ;R2 is digit
AddB3 S^#^A/0/,R2,-(R4) ;put in digit
SOBGtr R5,10$ ;loop
Ret ;return to caller
;This is the AST. The AST will be used to change the priority to a lower level
;by day so that it will have no real effect on the system performance.
.Save
.PSect Data,Long
Del8: .Quad 540000000000
Del11: .Quad 324000000000
NextTime:.Quad 0
NoPri: .Long 0
OldPri: .Long 4
Flag: .Byte 0
.Restore
.Entry MyAST,^M<R2,R3,R4>
TstB Flag ;see if it was 23:00
BNEq Raise ;No, then raise the priority
;It's now 8 in the morning
AddL2 Del8,NextTime ;Here's how long to wait
AdWC <4+Del8>,<4+NextTime> ;complete quadword addition
MovB S^#1,Flag ;set the flag
$SeTimr_S- ;set the timer
DayTim=NextTime,- ;the time
ASTAdr=MyAST ;the AST
$SetPri_S- ;reset the priority
Pri=NoPri,- ;low priority
PrvPri=OldPri ;the old priority
Ret ;with that all done, return...
Raise: ;It's now 11 at night
AddL2 Del11,NextTime ;Here's how long to wait
AdWC <4+Del11>,<4+NextTime> ;complete quadword addition
ClrB Flag ;clear the flag
$SeTimr_S- ;set the timer
DayTim=NextTime,- ;the time
ASTAdr=MyAST ;the AST
$SetPri_S- ;reset the priority
Pri=OldPri,- ;high priority
PrvPri=NoPri ;the old priority
Ret ;with that all done, return...
.End EF
@mdchaney
Copy link
Author

VAX-11 macro assembly - find "e" to any number of decimal places quite efficiently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment