在YASM 8086汇编中实现过滤后最后列浮点数求和
文本行过滤与浮点数求和实现
现有过滤规则
- 第二列不得包含字母u或v;
- 第三列数字的各位之和需等于7;
- 最后列数字需属于区间[2.34, 4.50]。
输入文件示例
B11;one;16;0;55;2.44 C1;two;8;0;17;3.77
第一行可通过所有过滤器。
当前需求
程序已正确实现上述所有过滤器,现在需要额外完成:计算通过过滤的行中最后列浮点数的总和,不确定正确实现方式。
现有最后列过滤函数(汇编)
procBelongsToInterval push ax xor ax, ax .first: mov al, [di] inc di cmp al, '-' je .break cmp al, '2' je .firstBound cmp al, '3' je .belongs cmp al, '4' je .secondBound jmp .break .firstBound: mov al, [di] inc di cmp al, '.' je .firstBound cmp al, '3' jb .break ja .belongs mov al, [di] cmp al, '4' jae .belongs jb .break .secondBound: mov al, [di] inc di cmp al, '.' je .secondBound cmp al, '5' ja .break jb .belongs mov al, [di] cmp al, '0' je .belongs ja .break .belongs: mov [numberBelongsToInterval], byte 1 jmp .end .break: mov [numberBelongsToInterval], byte 0 jmp .end .end: pop ax ret
浮点数求和实现方案
1. 提取最后列字符串并转换为浮点数
当前过滤函数仅做区间判断,未提取数值。需先把最后列的字符序列(如2.44)转换为可计算的浮点数:
- 遍历字符,拆分整数部分与小数部分;
- 计算整数部分数值(如
2直接转为整数2); - 计算小数部分数值(如
44转为44/100=0.44); - 合并两部分得到完整浮点数,或使用BCD转浮点数的方式处理。
2. 维护全局求和变量
定义一个8字节双精度浮点数全局变量sum_total,初始化为0。每次有符合所有过滤规则的行时,将转换后的最后列浮点数累加到该变量中。
3. 修改过滤逻辑,新增数值转换步骤
在procBelongsToInterval的.belongs分支中,调用字符串转浮点数的函数(需提前保存最后列的起始地址,避免di移动后无法回溯),将字符序列转为浮点数后执行累加操作。
字符串转浮点数示例思路
假设si指向最后列起始地址:
; si 指向最后列起始字符 xor ax, ax xor bx, bx ; 处理整数部分 .int_part: mov al, [si] cmp al, '.' je .dec_part sub al, '0' mov cx, 10 mul cx add bx, ax inc si jmp .int_part .dec_part: inc si xor ax, ax mov cx, 100 ; 适配两位小数,多位数可调整 .dec_loop: mov al, [si] cmp al, 0 ; 假设行末以0为终止符 je .calc_float sub al, '0' mov dx, ax mov ax, cx mov cx, 10 mul cx add ax, dx mov cx, ax inc si jmp .dec_loop .calc_float: ; bx为整数部分,cx为小数部分(两位) ; 使用FPU指令转换并累加 fild bx ; 加载整数部分到FPU栈 fild cx ; 加载小数部分 fild dword 100 ; 加载100 fdivp ; 小数部分除以100 faddp ; 整数+小数得到完整浮点数 fld qword [sum_total] ; 加载当前总和 faddp ; 累加新数值 fstp qword [sum_total] ; 保存新总和
4. 利用FPU指令简化浮点数运算
x86汇编中用浮点单元(FPU)处理浮点数更高效:
- 初始化总和:
fldz加载0到FPU栈,fstp qword [sum_total]保存到全局变量; - 每次转换后,用FPU指令完成累加,最后将结果回写到全局变量。
注意事项
- 确保最后列字符串格式合法(已通过过滤规则验证,无需额外格式校验);
- 根据实际输入的小数位数调整除数(如三位小数用1000);
- 进入过滤函数前必须保存最后列起始地址,避免
di移动后无法提取完整字符串。
内容的提问来源于stack exchange,提问作者user10203585
相关产品推荐
相关产品推荐

