如何在TASM中实现通用数值转字符串转换器?现有代码仅支持0-9
修正TASM数值转字符串转换器(支持大于9的数值)
问题根源分析
你的转换器无法处理大于9的数值,核心问题有两个:
- 存储数值的变量类型错误:
real_first_number定义为db(字节型),只能存储0-255的数值,超过就会溢出,导致后续转换出错。 - 字符串转数值时的操作宽度不匹配:原代码用字节寄存器(
al、bl、bh)进行乘法和加法,无法处理多位数的累加结果,同样会引发溢出。
关键修正点
1. 调整数值存储变量类型
将real_first_number和digit_saver从db改为dw,支持0-65535的数值范围:
real_first_number dw 0 digit_saver dw 1
2. 修正字符串转数值的逻辑
把字节操作改为字操作,确保累加和乘法不会溢出:
- 使用
ax、bx等字寄存器代替字节寄存器 - 用
movzx将字节值零扩展为字,避免高位垃圾值干扰计算 - 每次处理完一位后,将10的幂次除以10,适配下一位的权重
3. 修正数值转字符串的入口加载
在convert_counter_to_asc开始时,将完整的字数值加载到ax,而不是只加载低字节:
mov ax, [real_first_number] ; 代替原来的mov al, [real_first_number]
完整修正后的程序
assume cs: code, ds: data, ss: stck code segment begin: mov ax, data mov ds, ax ; 缓冲输入 mov ah, 0ah mov dx, offset first_input int 21h ; 标记输入字符串结束 mov bx, 0 mov bl, [first_input + 1] mov first_input[bx + 2], '$' ; 换行 mov ah, 02h mov dl, 0dh int 21h mov dl, 0ah int 21h ; 统计输入字符总数(含控制字节) mov di, 0 count_characters: mov al, first_input[di] cmp al, '$' je end_count inc di jmp count_characters end_count: mov cx, di sub cx, 2 ; 减去前两个控制字节,得到数字字符个数 ; ====================== 数字字符个数转字符串输出 ====================== mov si, offset counter_buffer push cx convert_counter_to_ascii: mov dx, 0 mov ax, cx mov bx, 10 div bx add dl, '0' dec si mov [si], dl mov cx, ax cmp cx, 0 jnz convert_counter_to_ascii mov ah, 09h mov dx, si int 21h ; 换行 mov ah, 02h mov dl, 0dh int 21h mov dl, 0ah int 21h pop cx ; 计算最高位的10的幂次 sub cx, 1 push cx cmp cx, 0 je just_one_digit pow_loop: mov ax, [digit_saver] mov bx, 10 mul bx mov [digit_saver], ax loop pow_loop pop cx add cx, 1 ; 恢复数字字符个数 push cx mov di, cx mov si, 2 ; ====================== 字符串转数值 ====================== convert_string_to_number: mov al, first_input[si] cmp si, di je just_one_digit inc si sub al, '0' movzx ax, al ; 字节转字,避免高位垃圾值 mov bx, [digit_saver] mul bx add [real_first_number], ax ; 更新10的幂次(除以10,为下一位准备) mov ax, [digit_saver] mov bx, 10 div bx mov [digit_saver], ax loop convert_string_to_number just_one_digit: mov si, cx add si, 2 mov al, first_input[si] sub al, '0' movzx ax, al add [real_first_number], ax ; ====================== 数值转字符串输出 ====================== mov si, offset first_number_buffer mov ax, [real_first_number] ; 加载完整的字数值 convert_counter_to_asc: mov dx, 0 mov bx, 10 div bx add dl, '0' dec si mov [si], dl mov cx, ax cmp cx, 0 jnz convert_counter_to_asc mov ah, 09h mov dx, si int 21h mov ax, 4C00h int 21h code ends data segment first_input db 10, ?, 10 dup (?) real_first_number dw 0 ; 改为字类型,支持更大数值 first_number_buffer db 6 dup ('$') counter_buffer db 6 dup('$') digit_saver dw 1 ; 同步改为字类型 data ends stck segment stack db 256 dup(?) stck ends end begin
额外说明
- 修正后的程序支持0-65535范围内的数值转换,涵盖了大部分常用的小整数场景
movzx指令用于将字节值零扩展为字,避免高位出现随机垃圾值导致计算错误- 字符串转数值时,每次处理完一位后将10的幂次除以10,适配下一位的权重(比如从100→10→1)
内容的提问来源于stack exchange,提问作者eightuponatime
相关产品推荐
相关产品推荐

