You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TASM x86汇编程序计算tan(x)后无法正确显示浮点数求解

解决TASM x86汇编中浮点数转字符串输出的问题

核心问题分析

你遇到的乱码是因为直接输出计算得到的二进制浮点数,而DOS中断(如int 21h的09h功能)仅识别ASCII字符串。必须先将数值(浮点数或定点数)转换为对应的ASCII字符序列,再调用中断输出。

针对x86汇编的数值转字符串实现方案

根据你泰勒展开的实现方式,以下提供两种常见场景的转换方案:

场景1:定点数转字符串(以放大1000倍的整数为例)

若计算结果以实际值 = 存储值 / 1000的定点数格式存储(如2.345存为2345),可按以下步骤转换:

  • 提取整数部分:用div指令将存储值除以1000,商为整数部分,余数为小数部分
  • 补全小数位:将余数补零至三位(不足时前置补0)
  • 逐位转ASCII:每一位数字加30h(ASCII中'0'的编码),组合成字符串

示例代码片段:

; 假设AX中存储放大1000倍的定点数(如2345代表2.345)
mov bx, 1000
div bx          ; AX=整数部分(2), DX=余数(345)

; 转换整数部分到字符串
mov si, offset int_str
call int_to_str

; 添加小数点
mov byte ptr [si], '.'
inc si

; 转换小数部分到字符串(补零到三位)
mov ax, dx
mov cx, 3
dec cx
fill_zero:
    mov bx, 10
    div bx
    add dl, 30h
    mov [si+cx], dl
    mov dl, 0
    loop fill_zero
add ax, 30h
mov [si], al

; 输出字符串(需以$结尾)
mov ah, 09h
mov dx, offset int_str
int 21h

; 整数转字符串子程序
int_to_str:
    mov cx, 0
    mov bx, 10
next_digit:
    xor dx, dx
    div bx
    add dl, 30h
    push dx
    inc cx
    cmp ax, 0
    jne next_digit
pop_digit:
    pop dx
    mov [si], dl
    inc si
    loop pop_digit
ret

int_str db 10 dup(0), '$'  ; 存储转换后的字符串,以$结尾

场景2:x87浮点数转字符串

若使用x87浮点单元计算tan(x)(结果在ST0寄存器),可利用fbstp指令将浮点数转为BCD码,再转ASCII:

  • 用fbstp [bcd_buffer]将ST0中的浮点数转为80位BCD码(含符号位、整数部分、小数部分)
  • 解析BCD缓冲区,提取符号、整数部分、小数部分
  • 逐位将BCD数字转为ASCII字符,组合成带符号的字符串

示例代码片段:

; 假设ST0中存储tan(x)的计算结果
fbstp [bcd_buffer]  ; 将浮点数转为BCD码存储到缓冲区

; 解析BCD码并转换为字符串
mov si, offset float_str
mov bx, offset bcd_buffer
mov al, [bx+9]      ; 取符号位(最高位为1表示负数)
test al, 80h
jz positive
mov byte ptr [si], '-'
inc si
positive:

; 转换整数部分(跳过前导零)
mov cx, 8
mov di, bx
skip_leading_zero:
    mov al, [di]
    cmp al, 0
    jnz start_int
    inc di
    loop skip_leading_zero
; 全零则补一个0
mov byte ptr [si], '0'
inc si
start_int:
mov cx, bx+8 - di
convert_int:
    mov al, [di]
    mov ah, al
    shr ah, 4
    add ah, 30h
    mov [si], ah
    inc si
    and al, 0Fh
    add al, 30h
    mov [si], al
    inc si
    inc di
    loop convert_int

; 添加小数点
mov byte ptr [si], '.'
inc si

; 转换小数部分
mov al, [bx+8]
mov ah, al
shr ah, 4
add ah, 30h
mov [si], ah
inc si
and al, 0Fh
add al, 30h
mov [si], al
inc si

; 输出字符串
mov ah, 09h
mov dx, offset float_str
int 21h

bcd_buffer dt 0     ; 80位BCD缓冲区
float_str db 20 dup(0), '$' ; 存储转换后的字符串

额外注意事项

  • 输出字符串必须以$结尾,否则int 21h的09h功能会输出乱码
  • 若使用纯整数运算的泰勒展开,需确定合适的数值缩放比例,避免精度丢失
  • 测试时可先转换固定数值(如1234转"1.234"),验证逻辑正确后再接入tan(x)的计算结果

内容的提问来源于stack exchange,提问作者Patryk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:55:23