IBM PC 8087 FPU、 66 82バイト
IBM PCのIntel 8087数学コプロセッサーのみを計算に使用します。
オフラインでお試しください!(DOSBoxなどで)。80年代に使用していたすべてのLotus 1-2-3スプレッドシート以外に、古いPCの退屈した8087チップを使いましょう。
9bdf 0783 c302 499b de07 83c3 0249 e342 9bde 2783 c302 49e3 399b de0f 83c3 0249
e330 9bde 3783 c302 49e3 2751 8b0f 9bd9 e883 f900 7413 9c7f 02f7 d99b d8c9 e2fb
9d7d 069b d9e8 9bd8 f159 83c3 0249 e302 ebb5 c3
未ゴルフ(組み立てなし):
START:
; RUN TESTS
MOV BX, OFFSET TST ; 5, 12, 23, 2, 4, 4, 2, 6, 7
MOV CX, CTST ; input array length
CALL WOMI ; calculate sequence
CALL PRINT_FLT ; output to console
MOV BX, OFFSET TST1 ; 5, 12, 23, 2, 4, -4, 2, 6, 7
MOV CX, CTST1
CALL WOMI
CALL PRINT_FLT
MOV BX, OFFSET TST2 ; -8, 50, 3, 3, -123, 4, 17, 99, 13
MOV CX, CTST2
CALL WOMI
CALL PRINT_FLT
MOV BX, OFFSET TST3 ; 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
MOV CX, CTST3
CALL WOMI
CALL PRINT_FLT
MOV BX, OFFSET TST4 ; 1,0,1,0,1,0
MOV CX, CTST4
CALL WOMI
CALL PRINT_FLT
MOV BX, OFFSET TST5 ; -9, -8, -1
MOV CX, CTST5
CALL WOMI
CALL PRINT_FLT
MOV BX, OFFSET TST6 ; 0, -3
MOV CX, CTST6
CALL WOMI
CALL PRINT_FLT
MOV AX, 4C00H ; exit to DOS
INT 21H
; TEST DATA
TST DW 5, 12, 23, 2, 4, 4, 2, 6, 7
CTST EQU ($-TST)/(SIZE TST) ; count of items on list
TST1 DW 5, 12, 23, 2, 4, -4, 2, 6, 7
CTST1 EQU ($-TST1)/(SIZE TST1) ; count of items on list
TST2 DW -8, 50, 3, 3, -123, 4, 17, 99, 13
CTST2 EQU ($-TST2)/(SIZE TST2) ; count of items on list
TST3 DW 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
CTST3 EQU ($-TST3)/(SIZE TST3) ; count of items on list
TST4 DW 1,0,1,0,1,0
CTST4 EQU ($-TST4)/(SIZE TST4) ; count of items on list
TST5 DW -9, -8, -1
CTST5 EQU ($-TST5)/(SIZE TST5) ; count of items on list
TST6 DW 0, -3
CTST6 EQU ($-TST6)/(SIZE TST6) ; count of items on list
; 8087 exponent: ST(0) = ST(0) ^ EXP
FIEXP MACRO EXP
LOCAL REPEAT, DONE
PUSH CX
MOV CX, EXP ; Exponent is count for loop
FLD1 ; load 1 into ST
CMP CX, 0 ; is exponent pos, neg or 0?
JZ DONE ; exit (with value 1) if exponent is 0
PUSHF ; save result flags for later
JG REPEAT ; if exp > 1 start calculation
NEG CX ; make exponent positive for loop
REPEAT:
FMUL ST(0), ST(1) ; multiply ST0 = ST0 * ST1
LOOP REPEAT
POPF ; retrieve flags from earlier
JGE DONE ; if exponent was negative, divide 1 by result
FLD1 ; push 1 into numerator
FDIV ST(0), ST(1) ; ST0 = 1 / ST1
DONE:
POP CX
ENDM
; Function WOMI: (Weapons of Math Instruction)
; input: BX - address of start of input array
; CX - length of input array
; output: ST - result on top of 8087 register stack
WOMI PROC
FILD WORD PTR [BX] ; load first item
ADD BX, 2 ; move to next
DEC CX
CALC:
FIADD WORD PTR [BX] ; add
ADD BX, 2 ; move to next
DEC CX ; decrement counter
JCXZ OUTPUT ; check if done
FISUB WORD PTR [BX] ; subtract
ADD BX, 2
DEC CX
JCXZ OUTPUT
FIMUL WORD PTR [BX] ; multiply
ADD BX, 2
DEC CX
JCXZ OUTPUT
FIDIV WORD PTR [BX] ; divide
ADD BX, 2
DEC CX
JCXZ OUTPUT
FIEXP [BX] ; exponent
ADD BX, 2
DEC CX
JCXZ OUTPUT
JMP CALC ; start again
OUTPUT:
RET
WOMI ENDP
PRINT_FLT PROC
; print top of 8087 stack
; scaling: 14 digits, 4 decimal places
; input: BX = address of a TBYTE (BCD) output buffer
; ST = value to display on top of 8087 stack
LEA BX, BUFF ; set BX to BCD output buffer
MOV AH, 2
MOV WORD PTR[BX], 10000 ; ten thousand (scale factor)
FIMUL WORD PTR[BX] ; scale up by 10000
FBSTP TBYTE PTR[BX] ; store as BCD
FWAIT ; sync 8088 and 8087
TEST BYTE PTR[BX+9], 80H ; check sign bit
JE PF_1 ; 0, goto PF_1
MOV DL, '-' ; output '-'
INT 21H
PF_1:
ADD BX, 8 ; point to high byte
MOV CH, 7 ; 14 digits before decimal point
MOV CL, 4 ; 4 shifts (8 bytes / 2 = 4 = 1 nibble)
MOV DH, 2 ; 2 times (8 bytes / 4)
PF_LOOP:
MOV DL, [BX] ; get BCD digits
SHR DL, CL ; move high digit to low nibble
OR DL, 30H ; convert to ASCII
INT 21H
MOV DL, [BX] ; get byte again
AND DL, 0FH ; mask out high digit
OR DL, 30H ; convert to ASCII
INT 21H ; output
DEC BX ; next byte
DEC CH ; decrement byte
JG PF_LOOP ; repeat if more bytes
DEC DH ; second time?
JE PF_DONE ; yes, done
MOV DL, '.' ; no, output decimal point
INT 21H
MOV CH, 2 ; 4 more digits after decimal point
JMP PF_LOOP ; go print digits
PF_DONE:
MOV DL, 0DH ; display newline CRLF
MOV AH, 2
INT 21H
MOV DL, 0AH
INT 21H
RET
PRINT_FLT ENDP
BUFF DT 0 ; output buffer for floating point digit string
_TEXT ENDS
END START
出力:
A>WOMI.COM
00000000000539.0000
-00000000000027.9136
-00000000001055.3569
00000000000256.0000
00000000000001.0000
-00000000000016.0000
-00000000000003.0000
入力はPROC(x86が関数に最も相当する)を介して行われ、BXはメモリ内のWORD配列へのポインタであり、CXはその中のアイテムの数であり、結果をSTに返します。
*注意:関数の実際のコードは 6682バイト。もちろん、コンソールに浮動小数点数を書き込むためのコード(クックブックコード)は83バイトです。テストプログラムとデータは183215バイト、.COM実行可能ファイル 305 合計380バイト。