双字节除法运算汇编程序请高手指导
80C51单片机双字节汇编程序:总数12345。先把个位存入10H。十位除10,商存入11H。百位除100,商存入12H。千位除1000,商存入13H。万位除10000,商存入14H。这里的12345是,0至12345之间的任意变化数(比如是AD读取的量值,在此时Bit位里的2进制数,0和1是随时变化,根本找不到逻辑。)
程序送人单片机就显示90000
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN: MOV DPTR, #12345 ; 加载双字节数12345
MOV R0, #10H ; 设置存储起始地址
; 提取个位(12345 MOD 10)
MOV A, DPL
MOV B, #10
DIV AB
MOV @R0, B ; 个位存入10H
INC R0
; 提取十位(12345/10 MOD 10)
MOV A, DPL
MOV B, #10
DIV AB
MOV A, B
MOV B, #10
DIV AB
MOV @R0, B ; 十位存入11H
INC R0
; 提取百位(12345/100 MOD 10)
MOV A, DPH
MOV B, #100
DIV AB
MOV @R0, A ; 百位存入12H
INC R0
; 提取千位(12345/1000 MOD 10)
MOV A, DPH
MOV B, #10
DIV AB
MOV @R0, A ; 千位存入13H
INC R0
; 提取万位(12345/10000)
MOV A, DPH
MOV B, #1
DIV AB
MOV @R0, A ; 万位存入14H
SJMP $ ; 程序结束
END 上面的程序是人工智能帮我写的,我送人单片机后就显示90000,按理应该显示12345,因为我总数是12345发布做除法运算 请将完整单片机型号,原理图,程序啥的能放的,都贴一下哈,不然工程师无法帮您判断
12345 十六进制 0x3039
0x39 / 10 == 57 / 10 == 5余7,怎么能用B得到5呢
给一个Ai写的参考:
; 仅使用DIV AB指令拆分12345为单个数字
; 存储地址: 0x14~0x10分别存放0x01~0x05
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN: ; 12345拆分为123和45两个8位数处理
MOV R0, #123 ; 高两位(123)
MOV R1, #45 ; 低两位(45)
; 提取万位1: 123 ÷ 100 = 1...23
MOV A, R0
MOV B, #100
DIV AB ; A=1, B=23
MOV 0x14, A ; 万位1存入0x14
; 提取千位2: 23 ÷ 10 = 2...3
MOV A, B ; A=23
MOV B, #10
DIV AB ; A=2, B=3
MOV 0x13, A ; 千位2存入0x13
; 提取百位3: 3 (来自上一步余数)
MOV 0x12, B ; 百位3存入0x12
; 提取十位4: 45 ÷ 10 = 4...5
MOV A, R1 ; A=45
MOV B, #10
DIV AB ; A=4, B=5
MOV 0x11, A ; 十位4存入0x11
; 提取个位5: 5 (来自上一步余数)
MOV 0x10, B ; 个位5存入0x10
HERE: SJMP HERE ; 程序暂停
END
ercircle 发表于 2025-8-25 19:35
12345 十六进制 0x3039
0x39 / 10 == 57 / 10 == 5余7,怎么能用B得到5呢
非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序走的通,
问题是如果这个12345是0至12345之间的任意变化数(比如是AD读取的量值,在此时Bit位里的2进制数,0和1是随时变化,根本找不到逻辑。)。那这个程序应该还是有问题。
请帮忙指导,感谢您
8H8K64U 发表于 2025-8-25 17:30
请将完整单片机型号,原理图,程序啥的能放的,都贴一下哈,不然工程师无法帮您判断...
这个单片机上面我写了,是8051.
这个只是个用来计算的子程序,和原理图是没有关系的
感谢您的帮助 非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序走的通,
问题是如果这个12345是0至12345之间的任意变化数(比如是AD读取的量值,在此时Bit位里的2进制数,0和1是随时变化,根本找不到逻辑。)。那这个程序应该还是有问题。
请帮忙指导,感谢您 道清 发表于 2025-8-25 20:43
非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序走 ...
没想到什么好思路诶,给个笨办法参考:
; 功能:将16位十六进制数转换为十进制,结果存于5字节缓冲区
; 入口:待转换数存于R6(高8位)和R7(低8位)
; 出口:转换结果存于30H-34H(30H为最高位,34H为最低位)
ORG 0000H
LJMP MAIN
ORG 1000H
MAIN: MOV R6, #030H ; 高8位示例值
MOV R7, #39H ; 低8位示例值
LCALL HEX2DEC ; 调用转换子程序
STOP: SJMP STOP ; 程序暂停
; 转换子程序:R6R7 -> 30H-34H
HEX2DEC:
MOV 30H, #0 ; 初始化5字节缓冲区(万位)
MOV 31H, #0 ; 千位
MOV 32H, #0 ; 百位
MOV 33H, #0 ; 十位
MOV 34H, #0 ; 个位
LCALL PROCESS_HIGH
RET ; 转换完成返回
; 十进位处理子程序
HANDLE_CARRY:
; 处理个位进位到十位
MOV A, 34H
MOV B, #10
DIV AB ; A=商(进位), B=余数(个位)
MOV 34H, B ; 保存个位
MOV R0, A ; 暂存进位值
; 处理十位进位到百位 - 累加进位
MOV A, 33H
ADD A, R0 ; 原有十位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(十位)
MOV 33H, B ; 保存十位
MOV R0, A ; 更新进位值
; 处理百位进位到千位 - 累加进位
MOV A, 32H
ADD A, R0 ; 原有百位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(百位)
MOV 32H, B ; 保存百位
MOV R0, A ; 更新进位值
; 处理千位进位到万位 - 累加进位
MOV A, 31H
ADD A, R0 ; 原有千位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(千位)
MOV 31H, B ; 保存千位
MOV R0, A ; 更新进位值
; 处理万位进位
MOV A, 30H
ADD A, R0 ; 原有万位值 + 进位
MOV 30H, A ; 保存万位(最多为65535,不会超过10)
RET
PROCESS_HIGH:
MOV A, R6
JZ PROCESS_LOW; 高8位为0且低8位<10,处理最后一位
; 高8位减1,补充十位25和个位6
DEC R6
MOV A, #6
ADD A, 34H
MOV 34H, A
MOV A, #25
ADD A, 33H
MOV 33H, A
; 处理各数位进位
LCALL HANDLE_CARRY
SJMP PROCESS_HIGH ; 再次检查高8位
PROCESS_LOW:
; 低8位处理
MOV A, R7
MOV B, #10
DIV AB ; 仅对低8位使用DIV
MOV R7, A ; 保存商到低8位
MOV A, B ; 余数作为当前十进制位
; 将余数累加到结果缓冲区的个位
ADD A, 34H
MOV 34H, A
; 将商累加到结果缓冲区的十位
MOV A,R7
ADD A, 33H
MOV 33H, A
MOV R7,#0
; 处理各数位进位
LCALL HANDLE_CARRY
RET
END
ercircle 发表于 2025-8-25 23:05
没想到什么好思路诶,给个笨办法参考:
感谢您,1.其中有暂停程序应该作废吧,要不然就卡这里了。2.SJMP PROCESS_HIGH ; 再次检查高8位。这条好像也应该删除是不是。
我送入单片机测试了,显示了还是不对。可能是我自己弄错,我先分析分析其中程序逻辑。
不过其中这两段程序我多想不通第1个:PROCESS_HIGH:
第2个:PROCESS_LOW:
让我先思考思考,感谢您