IBM PC 8087 FPU, 66 82字节
仅使用IBM PC的Intel 8087数学协处理器进行计算。
离线尝试!(在DOSBox或其他任何版本中)。给您旧PC上无聊的8087芯片做些什么,而不是您过去在80年代所做的所有那些Lotus 1-2-3电子表格。
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个字节。