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
相关产品推荐
相关产品推荐

