道清 发表于 2025-8-26 08:38:35

其他我多看的懂,也知道逻辑。就是这部分的逻辑我想不通,方便的话能详细解释吗?
谢谢



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


还有程序中的这条( SJMP    PROCESS_HIGH    ; 再次检查高8位)      这条好像是多余的吧

ercircle 发表于 2025-8-26 09:01:16

道清 发表于 2025-8-26 08:38
其他我多看的懂,也知道逻辑。就是这部分的逻辑我想不通,方便的话能详细解释吗?
谢谢


PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节再去处理低位。


PROCESS_LOW只执行一次,把低字节刷入十进制缓冲区。



“JZ      PROCESS_LOW; 高8位为0且低8位<10,处理最后一位” 这条注释改为 “高8位为0,跳转处理低八位”

Ayb_ice 发表于 2025-8-26 09:15:59

道清 发表于 2025-8-25 20:12
非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序 ...

网上搜索一下,需要循环比较

道清 发表于 2025-8-26 11:29:14

ercircle 发表于 2025-8-26 09:01
PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节 ...

看来我是想不通这个题目了,越看越不懂,等会我吧我的程序整理一下,麻烦您帮我看看,谢谢

道清 发表于 2025-8-26 12:20:46

ercircle 发表于 2025-8-26 09:01
PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节 ...
      SMG1       EQU      P1.0    ;数码管1
         SMG2       EQU      P1.1    ;数码管2
         SMG3       EQU      P1.3    ;数码管3
         SMG4       EQU      P1.2    ;数码管4
         ;数据       EQU      P3.0    ;164
         ;时间       EQU      P3.1    ;164
         FMQ         EQU      P3.4   ;蜂鸣器
         GNAN      EQU      P3.0   ;按下启动两只电机
         ANB         EQU      P3.1   ;按钮B
         ANA         EQU      P3.2   ;按钮A
         JDQ         EQU      P3.5    ;送料电机
         BJD         EQU      P1.6   ;数量到报警灯
         P1K         EQU      0EEH
         P2K         EQU      0EDH
         P3K         EQU      0ECH
         DLA         EQU      0EFH
         ORG         00H
         JMP         QQ

;------FH1------程序运行一次无返回-----------

;;----程序开始-------------
QQ:    CLR    FMQ   ;关闭蜂鸣器


      MOV   DPTR,#12345
      CALL    MAIN
       ;这四行的意思是把您分解出来的数 放到我显示的H里,我再调用显示程序,依次一位的显示
      MOV   38H,30H
      MOV   35H,31H
      MOV   36H,32H
      MOV   37H,33H
C1:   CALL   XS      ;调用显示程序
       JMP    C1         ;回调用显示程序
;-------------------------------------------------------------------------
;=================您写的程序开始=====我复制的========================
MAIN:   MOV   R6, DPH    ; 高8位示例值
      MOV   R7, DPL    ; 低8位示例值
      LCALL   HEX2DEC      ; 调用转换子程序
;STOP:   SJMP    STOP         ; 程序暂停
      RET
; 转换子程序: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
;=================您写的程序结束=====我复制的==============================================================================================================

    ;----74164显示----过程是把放在35H.36H。37H.38H,里的数字一次一位的送去显示在数码管上-----------------
    ;目前显示只有四位,只要能显示1234或2345,我再自己加一位

XS:   MOV      A,36H   ;把分解出来的放在36H里的数送到A里
      CALL   MB      ;调用码表   
      CALL   L164      ;调用164控制子程序
      CLR      SMG3      ;让控住脚接通负极,让这位数码管灯亮
      CALL   T2MS      ;让数码管延时点亮20毫秒
      SETB   SMG3      ;让控住脚接通正极,让这位数码管灯灭
      ;--------------------下面依次;亮;灭。数码管---四位共阴数码管-----我就不依次备注了-
      MOV      A,37H
      CALL   MB
      CALL   L164
      CLR      SMG4
      CALL   T2MS
      SETB   SMG4
      ;-------------------------
      MOV      A,35H
      CALL   MB
XSD:    CALL   L164
      CLR      SMG2
      CALL   T2MS
      SETB   SMG2
      ;-----------------------------
      MOV      A,38H
      CALL   MB
XSD1:   CALL   L164
      CLR      SMG1
      CALL   T2MS
      SETB   SMG1

      RET

;================L164=========================
L164:      MOV      65H,#08
         SETB       P3.3
         NOP
LOOP_0:    CLR      P3.3
         NOP
         RRC      A
         NOP
         MOV      P3.7,C
         NOP
         NOP
         SETB       P3.3
         NOP
         NOP
         NOP
         NOP
         DJNZ       65H,LOOP_0
         RET

;===========2MS延时===================
T2MS:       MOV       60H,#03H      ;08
D2MS_0:   MOV       61H,#03H      ;40
D2MS_1:   NOP
            DJNZ      61H,D2MS_1
            DJNZ      60H,D2MS_0
            NOP
            RET
;=============段码表===========================
MB:       INC       A
          MOVC      A,@A+PC
          RET
          DB      0EEH,22H,0BCH,0B6H,72H,0D6H,0DEH,0A2H,0FEH,0F6H,0FAH,5EH,0CCH,3EH,0DCH,0D8H,0CEH,7AH,8H,2EH,7CH,4CH,9AH,1AH,1EH,0F8H,0F2H,18H,0D2H,5CH,6EH,70H,8EH,74H,76H,94H,00H,4H,14H,94H,   ; 灯不亮是36;一点是37
          RET                                                                                                                                                                                          ;二点是38    ;三点是39
;=================================================
;--------------传感器AD信号-------------------
STCAD:
            MOV   0BCH,#11101100B          ;P1.4做传感器AD
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
WAD5:       MOV   A,0BCH
            JNB   ACC.4,WAD5
            MOV   A,0BDH
            MOV   10H,A
            SETB         P1.4

            RET
;--------------延时AD信号-------------------
STCAD1:
            MOV   0BCH,#11101101B          ;P1.5做延时AD
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
WAF5:       MOV   A,0BCH
            JNB   ACC.4,WAF5
            MOV   A,0BDH
            SUBB    A,#85
            JNC      AF1
            MOV      A,#0
            NOP
AF1:      NOP
            SETB         P1.5
            RET

;=============蜂鸣器响壹声===========================
FMQKJ:      SETB       FMQ
            MOV      R1,#255
Z1:         CALL       XS
            DJNZ       R1,Z1

            CLR      FMQ
            MOV      R1,#255
Z2:         CALL       XS
            DJNZ       R1,Z2


            RET

;=========读第X扇区============
       ;MOV   DPTR,#000H
DU:         MOV   0C7H,#10000010B    ;设置反映时间
            MOV   0C5H,#1       ;1是读的指令
            MOV   0C3H,DPH
            MOV   0C4H,DPL

            MOV   0C6H,#5AH      ;0C6H必须做2个动作
            MOV   0C6H,#0A5H   ;0C6H必须做2个动作
            NOP
            MOV   A,0C2H         ;读出来的数据放在0C2H
            NOP

            RET
    ;=============擦除===========
      ;    MOV   DPTR,#000H
CHA:      MOV   0C7H,#10000010B
            MOV   0C5H,#3
            MOV   0C3H,DPH
            MOV   0C4H,DPL
            MOV   0C6H,#5AH
            MOV   0C6H,#0A5H
            NOP

            RET
         ;=============写============
         ;    MOV   DPTR,#000H
XIE:      MOV   0C7H,#10000010B
            MOV   0C5H,#2
            MOV   0C3H,DPH
            MOV   0C4H,DPL

            MOV   0C2H,A         ;数据放在0C2H,写进去
            MOV   0C6H,#5AH
            MOV   0C6H,#0A5H
            NOP
            CALL    FZWCZ
             RET

;=============================================
;===========单片机片内储存防止误抄作============
FZWCZ:      MOV   07CH,#0
            MOV   0C5H,#0
            MOV   0C6H,#0
            MOV   0C3H,#80H
            MOV   0C4H,#0
            RET
END



ercircle 发表于 2025-8-26 14:15:53

道清 发表于 2025-8-26 12:20
SMG1       EQU      P1.0    ;数码管1
         SMG2       EQU      P1.1    ;数码管2
    ...

看到一些语法问题,
MAIN一般是程序入口,代码库当函数用建议另起各名字,并且用CALL调用MAIN没加RET,原程序是main执行完无限循环停止程序。
还有比如CALL   XS,CALL对应的代码块一般用RET结束,或者JMP去别的有RET结束的代码块,这个检查下哈



另外这个程序调试建议分两部分独立调试再组合
1.给个固定值数码管能正常显示
2.双字节转十进制缓存,这部分在仿真里就可以验证
3.再是联调



道清 发表于 2025-8-26 16:40:40

ercircle 发表于 2025-8-26 14:15
看到一些语法问题,
MAIN一般是程序入口,代码库当函数用建议另起各名字,并且用CALL调用MAIN没加RET,原 ...
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以免大家说跑偏了。
谢谢

ercircle 发表于 2025-8-26 17:19:38

道清 发表于 2025-8-26 16:40
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以 ...


我上面发的不一定编译时报错,运行时可能异常或跑飞。

有CALL就要有RET,不明白建议可以看下陈桂友老师的汇编课程:
陈桂友老师-STC单片机教学视频 国芯人工智能技术交流网站 - AI32位8051交流社区


先把上面问题搞明白,代码修改后再试下,然后讨论现存程序要发细节:

第一步只调试数码管,验证情况怎么样,缓冲区固定值4567能显示4567吗
第二步仿真 算法,输入什么,输出是什么,验证情况怎么样
第三步联调,现在什么问题,什么现象,


道清 发表于 2025-8-26 19:37:30

道清 发表于 2025-8-26 16:40
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以 ...

感谢,加   RET后就显示1234了

谢谢

我再试试其他

道清 发表于 2025-8-26 19:42:19

ercircle 发表于 2025-8-26 17:19
我上面发的不一定编译时报错,运行时可能异常或跑飞。

有CALL就要有RET,不明白建议可以看下陈桂友老师 ...
反复测试多成功了,感谢
页: 1 [2] 3 4
查看完整版本: 双字节除法运算汇编程序请高手指导