Created
September 26, 2014 16:06
-
-
Save mdchaney/4e2f3c35c20915fe9716 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
VAX-11 macro assembly - find "e" to any number of decimal places quite efficiently.