-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFLOAT.ASM
4956 lines (4247 loc) · 65.9 KB
/
FLOAT.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;float.asm
data segment word public
assume ds:data
extrn pointword:word,pointbyte:word,schoolflg:byte
extrn ascend:word
floatbias dw ?
thisfloatword dw ?
thisfloatbyte dw ?
thispointdeci dw ?
pointtmp dw ?
biasmem dw ?
data ends
code segment public
assume cs:code,ds:data
public pointascin
public divIorFdisi,fardivIorFdisi
public intin,int_ent,farint_ent
public floorin,ceilin,roundin,fixin
public floor_ent,ceil_ent,round_ent,fix_ent
public store_float,justlengthFdi,normalizeFdi
public int2floatbxcurrent
public floatdivdiax,floatmuldiax
public farfloatdivdiax
public add_integer_float,add_float_integer,add_float_float
public mul_integer_float,mul_float_integer,mul_float_float
public div_integer_float,div_float_integer,div_float_float
public idiv_integer_float,idiv_float_integer,idiv_float_float
public addFFdisi,subFFdisi,mulFFdisi,divFFdisi,idivFFdisi
public compFFdisi
public faraddFFdisi,farsubFFdisi,farmulFFdisi
public add_float_rational,add_rational_float
public mul_float_rational,mul_rational_float
public div_float_rational,div_rational_float
public cmp_float_float
public cmp_integer_float,cmp_float_integer
public cmp_rational_float,cmp_float_rational
public divin,fardivin,divAAdisi,fardivAAdisi
public mulIorFdisi,inverseFdi
public real2floatbxjust,farreal2floatbxjust
public real2float0,farall2float0
extrn farbinasc:far,binascret:near
extrn prchr:near,prntbx:near,print_calcsp_out:near
public squareIFCdi,farsquareIFCdi
extrn squareIdi:near
public floatsetdiax,farfloatsetdiax
public squareFdi,farsquareFdi
public factorialFFdiax,farfactorialFFdiax
public powerFCdiax,farpowerFCdiax
public float2intbx,farfloat2intbx
public roundupF
extrn overloaddiv:near
sftupdiax:
;in ax: difference
; di: base adr
;NOTE: non checking overflow!!
; higher address may be destroyed
; must check higher address
mov cx,[di]
and cx,lenmask
jz sftupdiaxret
push ax ;/*
add [di],ax
add di,cx
add di,cx
mov si,di
add di,ax
add di,ax
add ax,cx
; cmp ax,limitword
; ja sftupdiaxover
std
rep movsw
pop cx ;*/
xor ax,ax
rep stosw
cld
sftupdiaxret:
ret
;sftupdiaxover:
; jmp ovrerr
divdibyax:
;in ax: divisor
;out ax: length of result
PUSH DX
PUSH SI
PUSH DI
PUSH BP
MOV BP,ax
MOV CX,[DI]
MOV [ANSLEN],CX ;expected length of result
XOR DX,DX ;remainder
ADD DI,CX
ADD DI,CX
MOV SI,DI ;SI=DI=MSW
STD
divditen10:
MOV AX,[DI]
DIV BP
STOSW
myloop divditen10
CLD
; shr bp,1
; cmp dx,bp
; jb divditen50
;
; ; roundup
;
; stc
;divditen20:
; winc di
; adc word ptr [di],0
; jc divditen20
divditen50:
mov ax,[anslen]
CMP [SI],CX ;CX=0
JNE divditen100
;decrement length since MSW = 0
dec ax
divditen100:
POP BP
POP DI
POP SI
POP DX
mov [di],ax ;set new length
ret
justlengthFdi:
;inp di: base adr
;make length to [pointword]
mov ax,[di]
lea bx,[di+4]
and ax,lenmask
jz jusstlenret
dec ax
sub ax,[pointword]
jz jusstlenret
jb jusstlenup
jusstlendown:
sub [di],ax ;rewrite attr
mov cx,[pointword]
mov di,bx
mov si,bx
add si,ax
add si,ax
mov ah,[si-1] ;lower byte
rep movsw
add ah,ah
jnc jusstlenret
jmp roundupF ;call & ret
jusstlenret:
ret
jusstlenup:
neg ax
mov cx,[pointword]
add [di],ax ;rewrite attr
inc cx
add di,cx
add di,cx
dec cx
mov si,di
sub si,ax
sub si,ax
sub cx,ax
std
rep movsw
mov cx,ax
xor ax,ax
rep stosw
cld
ret
normalizeFdi:
;inp di: base adr
;cut higher 0
mov cx,[di]
jcxz normalret
mov si,di
and cx,lenmask
add cx,cx
xor al,al
add di,cx
sub cx,2
inc di ;MSB
mov dx,cx
mov bx,di
std
repe scasb
cld
je normalset0 ;all 0
inc di
inc cx ;cx = number of non 0 bytes
sub dx,cx ;dx = number of higher 0 bytes
sub [si+2],dx ;rewrite bias
mov si,di ;src MSB
mov di,bx ;dst MSB
std
rep movsb
mov cx,dx
xor al,al
rep stosb
cld
normalret:
ret
normalset0:
mov word ptr [si],0
ret
store_float:
;convert integer part to float
mov bx,[calcsp]
mov cx,[bx]
and cx,lenmask
push cx ;/*
call int2floatbxcurrent
;get fractional part
inc bp
mov al,[bp]
call parnumsub ;get as an integer
;copy to mulwork
mov ax,[calcsp]
copyF ax,mulwork
add ax,unitbyte
mov [calcsp],ax
pop dx ;*/
cmp dx,[pointword]
jbe strf10 ;must calc frac part
jmp strf100
strf10:
or dx,dx
jnz strf30
;slide up by currentword + pointword + 1
mov di,mulwork
mov ax,[di]
and ax,lenmask
add ax,[pointword]
inc ax
push ax ;/*
call sftupdiax
;division by 10000 or 10
mov si,mulwork
pop dx ;*/
mov ax,[si]
mov di,si
inc dx
add si,dx
add si,dx ;adr of intpart
strf15:
cmp ax,dx
je strf20 ;if intpart = 1 word
mov ax,10000
call divdibyax
jmp strf15
strf20:
cmp word ptr [si],1
je strf25 ;if int part = 1
mov ax,10
call divdibyax
jmp strf20
strf25:
;set fractional part
lea di,[si-1] ;fraction MSB
mov si,mulwork
mov cx,di
sub cx,si
dec cx
xor al,al
mov dx,cx
std
repe scasb
cld
je strfset0 ;if 0.0
sub dx,cx
dec dx ;dx = number of higher 0
neg dx
lea si,[di+1] ;si = non zero top
mov di,[calcsp]
mov ax,[pointword]
sub si,ax
sub si,ax
mov cx,ax
inc si
inc ax
or ax,pointmask
stosw
mov [di],dx ;bias
winc di
mov ah,[si-1] ;used by roundup
mov bx,di ;
rep movsw
jmp strf90
strfset0:
mov word ptr [si],0
jmp strf100
strf30:
mov di,mulwork
mov ax,[pointword]
inc ax ;1 more word
call sftupdiax ;shift up for division
mov si,mulwork
mov ax,[si]
mov dx,[pointword]
add dx,2
mov di,si
add si,dx
add si,dx ;adr of intpart
strf40:
cmp ax,dx
je strf50 ;if intpart = 1 word
mov ax,10000
call divdibyax
jmp strf40
strf50:
cmp word ptr [si],1
je strf60 ;if int part = 1
mov ax,10
call divdibyax
jmp strf50
strf60:
;copy fractional part
mov di,[calcsp]
mov ax,[di+2] ;bias
add di,4
mov cx,[pointword]
add cx,cx
sub cx,ax ;byte length of rest data
sub si,cx ;MSB of frac part
mov bx,di ;used by roundupF
mov ah,[si-1] ;
rep movsb
strf90:
add ah,ah
jnc strf100
call roundupF
;done ?
strf100:
mov al,[bp]
cmp al,'e'
je strf120
strf105:
mov al,[bp]
cmp al,9eh ;code of complex
je strf110
ret
strf110:
jmp store_complex
strf120:
inc bp
mov dx,1 ;dx is sign
mov al,[bp]
inc bp
cmp al,ncode
je strf105 ;bias = 0
cmp al,0deh ;code of -
jne strf125
mov dx,-1
mov al,[bp]
inc bp
strf125:
cmp al,ncode1
jne strfovererr
mov ax,[bp]
winc bp
cmp dx,1
jne strfminus
strfplus:
mov di,[calcsp]
mov cx,ax
push ax ;/*
shr cx,2
jz strf126a
strf126:
push cx
mov ax,10000
call floatmuldiax
pop cx
myloop strf126
strf126a:
pop cx ;*/
and cx,3
jz strf126c
mov ax,10
dec cx
jz strf126b
mov ax,100
dec cx
jz strf126b
mov ax,1000
strf126b:
call floatmuldiax
strf126c:
jmp strf105
strfminus:
mov di,[calcsp]
mov cx,ax
push ax ;/*
shr cx,2
jz strf127a
strf127:
push cx
mov ax,10000
call floatdivdiax
pop cx
myloop strf127
strf127a:
pop cx ;*/
and cx,3
jz strf127c
mov ax,10
dec cx
jz strf127b
mov ax,100
dec cx
jz strf127b
mov ax,1000
strf127b:
call floatdivdiax
strf127c:
jmp strf105
strfovererr:
jmp ovrerr
farslide1:
call slide1
retf
floatover:
jmp ovrerr
slide1:
;slide down x_0,x_1,...,x_2F with offset 1
;increment bias word
;inp bx:base adr + 4
; bx is unchanged
mov cx,[bx-4]
mov ax,[bx-2]
and cx,lenmask
inc ax
dec cx
cmp ax,floatbiasover
jge floatover
mov di,bx
mov [bx-2],ax
lea si,[bx+1]
mov al,[bx] ;mem low byte
rep movsw
add al,al
jc roundupF ;cross reference
ret
roundupF:
;inp bx:base adr + 4
; bx is unchanged
mov cx,[bx-4]
mov si,bx
and cx,lenmask
stc
dec cx
roundupF10:
jnc roundupF20
adc word ptr [si],0
winc si
myloop roundupF10
jc goslide1
roundupF20:
ret
goslide1:
mov word ptr [si],1 ;highest word
jmp slide1 ;cross reference
floatmulby2:
xor ax,ax ;clc
fmulsubby2lp:
rcl word ptr [si],1
winc si
myloop fmulsubby2lp
rcl ax,1 ;get overflow
mov [si],ax
pop di
ret
farfloatmulaxsub:
call floatmulaxsub
retf
floatmulaxsub:
push di
mov bx,ax ;multiplier
mov si,di
mov cx,[si]
add si,4
and cx,lenmask
dec cx
mov [thisfloatword],cx
cmp ax,2
je floatmulby2
if FLG32
shr cx,1
jc fmulaxsub16 ;ubnormal case(storef,...)
set32
shl bx,16
set32
shr bx,16
set32
xor di,di ;carry
fmulaxsublp:
set32
mov ax,[si]
set32
mul bx
set32
add ax,di
set32
adc dx,0
set32
mov [si],ax
set32
mov di,dx
qinc si
myloop fmulaxsublp
jmps fmulaxsubout
fmulaxsub16:
rcl cx,1
endif
xor di,di ;carry
fmulaxsub16lp:
mov ax,[si]
mul bx
add ax,di
adc dx,0
mov [si],ax
mov di,dx
winc si
myloop fmulaxsub16lp
fmulaxsubout:
mov [si],di ;overflow
mov ax,di ;overflow
pop di
ret
farfloatmuldiax:
call floatmuldiax
retf
floatmuldiax:
;[di] *= ax
; reserve di
; non assuming es=ds
cmp word ptr [di],0
je floatmulaxret
call floatmulaxsub
or ax,ax
jz floatmulaxret ;no overflow
or ah,ah
jnz floatmulaxjp3 ;if 2bytes overflow
floatmulaxjp2:
lea si,[di+4]
mov ax,[si-2]
inc ax
cmp ax,floatbiasover
jge floatmulover
mov [si-2],ax ;set bias
mov cx,[thisfloatword]
lodsb
add al,al ;check lower bit for round
floatmulaxlp2: ;add carry with slide copy
lodsw
adc ax,0
mov [si-3],ax
myloop floatmulaxlp2
jnc floatmulaxret
mov byte ptr [si-1],1
jmp floatmulaxjp2
floatmulaxret:
ret
floatmulover:
jmp ovrerr
floatmulaxjp3: ;2bytes overflow
lea si,[di+4]
mov ax,[si-2]
add ax,2
cmp ax,floatbiasover
jge floatmulover
mov [si-2],ax ;set bias
mov cx,[thisfloatword]
lodsw
add ah,ah ;check lower bit for round
floatmulaxlp3: ;add carry with slide copy
lodsw
adc ax,0
mov [si-4],ax
myloop floatmulaxlp3
;must non carry
jmp floatmulaxret
floatdivdiaxcomplex:
push di
add di,2
mov si,di
mov dx,[di]
and dx,lenmask
inc dx
add si,dx
add si,dx
push ax
push si ;top of im part
call floatdivdiax
cmp word ptr [di],0
je floatdivdiaxcomplexre0
floatdivdiaxcomplexjp:
pop di
pop ax
call floatdivdiax
cmp word ptr [di],0
je floatdivdiaxcomplexim0
pop di
mov ax,[di+2]
mov si,di
and ax,lenmask
add si,ax
add si,ax
mov dx,[si+4]
and dx,lenmask
add ax,2
add ax,dx
or ah,complexmaskhigh
mov [di],ax
ret
floatdivdiaxcomplexre0: ;if real part = 0
pop si
add di,2
push di
copy_si2di
jmp floatdivdiaxcomplexjp
floatdivdiaxcomplexim0: ;if imag part = 0
pop di
push di
lea si,[di+2]
copy_si2di
pop di
ret
if FLG32
floatdivby2:
shr cx,1
sub si,2
xor ax,ax ;clc
floatdivby2lp:
set32
rcr word ptr [si],1
qdec si
myloop floatdivby2lp
rcr ax,1 ;get carry
jmps floatdivdiaxjp
else
floatdivby2:
xor ax,ax ;clc
floatdivby2lp:
rcr word ptr [si],1
wdec si
myloop floatdivby2lp
rcr ax,1 ;get carry
jmps floatdivdiaxjp
endif
farfloatdivdiax:
call floatdivdiax
retf
floatdivdiaxilg:
jmp ilgerr
floatdivdiax:
;[di] /= ax
; [di] are float or complex
; reserve di
mov si,di
mov bx,ax ;divisor
mov cx,[si]
add si,2
mov dx,cx
and cx,lenmask
jz floatdivaxret
and dh,attribmaskhigh
cmp dh,complexmaskhigh
je floatdivdiaxcomplex
cmp dh,pointmaskhigh
jne floatdivdiaxilg
dec cx
mov [thisfloatword],cx
add si,cx
add si,cx ;adr of MSW
xor dx,dx ;carry
push si
cmp ax,2
je floatdivby2
shr cx,1
wdec si
set32
xor dx,dx
set32
shl bx,16
set32
shr bx,16
floatdivaxlp:
set32
mov ax,[si]
set32
div bx
set32
mov [si],ax
qdec si
myloop floatdivaxlp
set32
xor ax,ax
set32
div bx
set32
ror ax,16 ;ax=next, higher=next to next
floatdivdiaxjp:
pop si
mov cx,[si]
or ch,ch
jz floatdivaxup ;if higher 0
lea si,[di+2]
add ah,ah ;check lower bit for round
floatdivaxlp1:
jnc floatdivaxret
winc si
adc word ptr [si],0
jmp floatdivaxlp1
floatdivaxup:
or cl,cl
jz floatdivaxup2 ;2 bytes higher 0
;1 byte higher 0 case
mov cx,[thisfloatword]
mov di,si
dec si
std
rep movsw
mov [di+2],ah
cld
sub di,2
mov cx,[di+2] ;set bias
dec cx
jmp floatdivaxupout
floatdivsetdi0:
mov word ptr [di],0
floatdivaxret:
ret
floatdivaxup2:
;2 bytes higher 0 case
mov cx,[thisfloatword]
dec cx
mov di,si
sub si,2
std
rep movsw
mov [di],ax
cld
sub di,4
set32
rol ax,8 ;al = next byte
mov cx,[di+2] ;set bias
sub cx,2
floatdivaxupout:
cmp cx,floatbiasunder
jle floatdivsetdi0
mov [di+2],cx
add al,al
jnc fixedcheck
lea bx,[di+4]
push di
call roundupF
pop di
fixedcheck:
cmp [fixedflag],0
je floatdivaxret
mov ax,[pointword]
add ax,ax
add ax,cx
jle floatdivsetdi0
add ax,3
shr ax,1
and ax,0fffeh
mov cx,[di]
and cx,lenmask
dec cx
cmp ax,cx
jae xxxret
sub cx,ax
sub [di],cx
mov bx,di
add di,4
mov si,di
add si,cx
add si,cx
mov cx,ax
rep movsw
mov di,bx
xxxret:
jmp floatdivaxret
;
; arithmetic for floating numbers
;
;
;* multiplication of integers & floats
; Note:
; if float is included then
; integer will be translated to float (may be rounded)
mulIorFdisi: ;can treat integer & float
mov ax,[di]
mov dx,[si]
and ax,attribmask
jz muldisiifint
and dx,attribmask
jz muldisiiffloatint
jmp mulFFdisi
muldisiifint:
and dx,attribmask
jz mulIIdisi
jmp mul_integer_float
muldisiiffloatint:
jmp mul_float_integer
align 4
;
;* multiplicaation of floating numbers
; [di] *= [si] ;both float
; reserve [si] (si destroyed)
; use mulwork
farmulFFdisi:
call mulFFdisi
retf
mulFFdisi:
mul_float_float:
mov cx,[di]
mov bx,[si]
mov al,ch
mov ah,bh
and cx,lenmask
jz mulFFret ;if [di] = 0
and bx,lenmask
jz mulFFset0 ;if [si] = 0
dec cx
dec bx
push ax ;attrib
winc si
winc di
mov ax,[si]
add ax,[di]
push ax ;new bias
winc di
winc si
push di
call far ptr farmulFFsub
pop di
sub di,4
mov si,mulwork
mov dx,[si]
shr dx,1
pop bx ;new bias
pop ax ;attrib
xor ah,al
and ax,signmask
jmp getfloat ;call & ret
mulFFset0:
mov word ptr [di],0
mulFFret:
ret
;
; integer data in [si]
; to float data in [di]
; si must >= di+2
; ax: sign
; dx: precision
; bx: sum of bias