道清 发表于 2025-8-25 14:55:53

双字节除法运算汇编程序请高手指导

80C51单片机双字节汇编程序:总数12345。先把个位存入10H。十位除10,商存入11H。百位除100,商存入12H。千位除1000,商存入13H。万位除10000,商存入14H。
这里的12345是,0至12345之间的任意变化数(比如是AD读取的量值,在此时Bit位里的2进制数,0和1是随时变化,根本找不到逻辑。)



程序送人单片机就显示90000

道清 发表于 2025-8-25 14:56:57

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

道清 发表于 2025-8-25 15:03:42

上面的程序是人工智能帮我写的,我送人单片机后就显示90000,按理应该显示12345,因为我总数是12345发布做除法运算

8H8K64U 发表于 2025-8-25 17:30:03

请将完整单片机型号,原理图,程序啥的能放的,都贴一下哈,不然工程师无法帮您判断

ercircle 发表于 2025-8-25 19:35:27



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


道清 发表于 2025-8-25 20:12:57

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是随时变化,根本找不到逻辑。)。那这个程序应该还是有问题。

请帮忙指导,感谢您

道清 发表于 2025-8-25 20:30:39

8H8K64U 发表于 2025-8-25 17:30
请将完整单片机型号,原理图,程序啥的能放的,都贴一下哈,不然工程师无法帮您判断...

这个单片机上面我写了,是8051.
这个只是个用来计算的子程序,和原理图是没有关系的

感谢您的帮助

道清 发表于 2025-8-25 20:43:06

非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序走的通,
问题是如果这个12345是0至12345之间的任意变化数(比如是AD读取的量值,在此时Bit位里的2进制数,0和1是随时变化,根本找不到逻辑。)。那这个程序应该还是有问题。

请帮忙指导,感谢您

ercircle 发表于 2025-8-25 23:05:53

道清 发表于 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

道清 发表于 2025-8-26 05:26:12

ercircle 发表于 2025-8-25 23:05
没想到什么好思路诶,给个笨办法参考:

感谢您,1.其中有暂停程序应该作废吧,要不然就卡这里了。2.SJMP    PROCESS_HIGH    ; 再次检查高8位。这条好像也应该删除是不是。

我送入单片机测试了,显示了还是不对。可能是我自己弄错,我先分析分析其中程序逻辑。

不过其中这两段程序我多想不通第1个:PROCESS_HIGH:
第2个:PROCESS_LOW:

让我先思考思考,感谢您
页: [1] 2 3 4
查看完整版本: 双字节除法运算汇编程序请高手指导