16位无符号整数转ASCII十六进制字符串代码覆盖问题修复问询
修复16位无符号整数转十六进制ASCII字符串的覆盖问题
需求说明
将16位无符号整数转换为4位十六进制ASCII字符串:
- 输入:数值高字节存于R5,低字节存于R6;ASCII字符串起始地址由R7指定,初始化代码为
MOV R5,#HIGH(NUMBER)、MOV R6,#LOW(NUMBER)、MOV R7,#STR_ADDR_IRAM - 输出:从R7指向的内存地址开始,连续存储转换后的4位十六进制ASCII字符(可选添加字符串结束符)
现有问题
当前代码的十六进制转ASCII逻辑本身可行,但存在核心问题:每次转换得到的字符直接覆盖寄存器R7的数值,而非写入R7指向的内存地址;同时未更新指针地址,导致最终仅保留最后一个转换的字符,前面的结果全部丢失。
原代码
MOV A, R6 ;Get hexadecimal data byte from RAM location R6 MOV R2, A ;Store in R2 ANL A, #0FH ;Get the lower nibble ACALL ASCII ;Convert to ASCII MOV R7, A ;Store the lower digit's ASCII code MOV A, R2 ;Get back the number SWAP A ;Swap nibbles in A ANL A, #0FH ;Get the upper BCD digit ACALL ASCII ;Convert to ASCII MOV R7, A ;Store the upper digit´s ASCII code MOV A, R5 ;Get hexadecimal data byte from RAM location R5 MOV R2, A ;Store in R2 ANL A, #0FH ;Get the lower nibble ACALL ASCII ;Convert to ASCII MOV R7, A ;Store the lower digit's ASCII code MOV A, R2 ;Get back the number SWAP A ;Swap nibbles in A ANL A, #0FH ;Get the upper BCD digit ACALL ASCII ;Convert to ASCII MOV R7, A ;Store the upper digit´s ASCII code RET ASCII : CLR C ;ASCII conversion MOV R4, A ;Store A to R4 SUBB A, #0AH ;Substract accumulator JC next ;If carry, jump to next MOV A, R4 ;No carry so bring back R4 to A ADD A, #07H ;No carry, so add 7 to A SJMP SUM ;Jump to SUM next: MOV A, R4 ;Bring back R4 to A SUM: ADD A, #30H ;Add 30 to A RET END
修复后的代码
MOV A, R5 ; 获取16位整数的高字节 MOV R2, A ; 暂存高字节数据到R2 SWAP A ; 交换高低四位,先处理高字节的高四位(对应十六进制第1位) ANL A, #0FH ; 提取高四位 ACALL ASCII ; 转换为ASCII码 MOV @R7, A ; 将ASCII字符写入R7指向的内存地址 INC R7 ; 指针地址自增,准备存储下一个字符 MOV A, R2 ; 取回暂存的高字节数据 ANL A, #0FH ; 提取高字节的低四位(对应十六进制第2位) ACALL ASCII ; 转换为ASCII码 MOV @R7, A ; 写入内存 INC R7 ; 更新指针 MOV A, R6 ; 获取16位整数的低字节 MOV R2, A ; 暂存低字节数据到R2 SWAP A ; 交换高低四位,处理低字节的高四位(对应十六进制第3位) ANL A, #0FH ; 提取高四位 ACALL ASCII ; 转换为ASCII码 MOV @R7, A ; 写入内存 INC R7 ; 更新指针 MOV A, R2 ; 取回暂存的低字节数据 ANL A, #0FH ; 提取低字节的低四位(对应十六进制第4位) ACALL ASCII ; 转换为ASCII码 MOV @R7, A ; 写入最后一个字符 ; 可选:添加字符串结束符(若需要C风格字符串) ; MOV A, #00H ; MOV @R7, A RET ASCII : CLR C ; 十六进制转ASCII子程序 MOV R4, A ; 暂存当前数值到R4 SUBB A, #0AH ; 比较数值是否≥10 JC next ; 若数值<10(有进位),跳转到next MOV A, R4 ; 数值≥10,取回原数值 ADD A, #07H ; 加上偏移量,转换为A-F的ASCII码 SJMP SUM ; 跳转到统一加30H的步骤 next: MOV A, R4 ; 数值<10,取回原数值 SUM: ADD A, #30H ; 加上30H,转换为0-9的ASCII码 RET END
修复要点
- 写入内存而非覆盖寄存器:将
MOV R7, A替换为MOV @R7, A,这是8051汇编中间接寻址的写法,用于将累加器A的值写入到R7寄存器指向的内存单元,而非修改R7本身的指针值。 - 更新指针地址:每次写入字符后执行
INC R7,让指针指向内存中的下一个单元,确保后续字符不会覆盖已写入的结果。 - 调整转换顺序:原代码的转换顺序不符合16位整数的十六进制显示逻辑(原顺序为低字节低四位→低字节高四位→高字节低四位→高字节高四位),修复后调整为高字节高四位→高字节低四位→低字节高四位→低字节低四位,保证输出的ASCII字符串顺序与数值的十六进制表示一致。
内容的提问来源于stack exchange,提问作者Tomás Prieto Calabuig
相关产品推荐
相关产品推荐

