Compile-time calculation: Difference between revisions

→‎{{header|6502 Assembly}}: Add implementation.
(OCaml: Add flambda compile-time reductions)
(→‎{{header|6502 Assembly}}: Add implementation.)
Line 57:
+ L R1,=A(3628800) load reg with factorial
</pre>
=={{header|6502 Assembly}}==
{{works with|ca65 targeting the C-64}}
 
The ca65 cross-assembler supports computing and storing double-word (32-bit) integer values; unfortunately most 8-bit systems have no built-in support for manipulating such values. In this solution the assembler computes the actual value of 10! and stores it as a 32-bit integer; the runtime code converts that to floating point using ROM routines, dealing with the 16-bit halves of it one at a time.
 
<lang 6502>; Display the value of 10!, which is precomputed at assembly time
;
fac = $61 ; location of the floating point accumulator used by ROM routines
facsgn = fac+5 ; specific location of the sign byte
 
sys = $9e ; BASIC token for the SYS command to call our ML routine
 
start_of_basic = $0801 ; where our code is loaded
 
; ROM routines used
putfac = $aabc ; print out the value in the FAC
givayf = $b391 ; convert 16-bit integer in AY to floating-point value in FAC
fmult = $ba28 ; multiply FAC by float in memory
fadd = $b867 ; add float in memory to FAC
movfm = $bbd4 ; copy FAC to memory
 
; custom BASIC loader
.word start_of_basic
.org start_of_basic
.word last_line
.word *
.byte sys
.byte $30 + < (main/1000)
.byte $30 + <((main .mod 1000)/100)
.byte $30 + <((main .mod 100)/10)
.byte $30 + < (main .mod 10)
.byte 0
last_line:
.word 0
 
; 65536 as a float for multiplying the top half
fp65536: .byte 145,0,0,0,0,0
 
; the actual value to print
tenfactorial: .dword 10*9*8*7*6*5*4*3*2*1
 
; a place to stash partial results whlie using the FAC for other operations
fac_copy: .res 6
 
main:
; convert the upper half
ldy tenfactorial+2
lda tenfactorial+3
jsr givayf
 
; and multiply by 65536
lda #<fp65536
ldy #>fp65536
jsr fmult
 
; stash it
ldx #<fac_copy
ldy #>fac_copy
jsr movfm
 
; now convert the lower half
ldy tenfactorial
lda tenfactorial+1
jsr givayf
 
; since it's the bottom half of a larger number
; it may have the high bit set, which will cause the above to
; treat it as negative. If that happened, correct by adding 65536.
lda facsgn
beq ok ; it's positive, so skip the correction
 
; it's negative, so add 65536
lda #<fp65536
ldy #>fp65536
jsr fadd
 
ok:
; FAC now has lower half; add our copy of upper half
lda #<fac_copy
ldy #>fac_copy
jsr fadd
 
; and print out the result
jsr putfac
rts</lang>
 
{{Out}}
<pre>
**** COMMODORE 64 BASIC V2 ****
 
64K RAM SYSTEM 38911 BASIC BYTES FREE
 
READY.
LOAD"*",8,1
 
SEARCHING FOR *
LOADING
READY.
RUN:
3628800
 
READY.</pre>
 
=={{header|68000 Assembly}}==
VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants.
Line 65 ⟶ 168:
LEA tenfactorial,A1 ;load into A1 the memory address 10! = 0x375F00
ADD.L #tenfactorial,D2 ;add 10! to whatever is stored in D2 and store the result in D2</lang>
 
 
=={{header|Ada}}==
1,480

edits