cjaizss 发表于 2025-7-29 10:57:41

这段汇编测试代码行为让我觉得诡异 | 已解决

;这一段只是让两个灯亮一会灭掉,说白了证明灯是好的
SETB P3.2
SETB P3.4
MOV R0, #0
LINE_YYY1:
MOV R1, #0
LINE_YYY2:
MOV R2, #0
DJNZ R2, $
DJNZ R1, LINE_YYY2
DJNZ R0, LINE_YYY1
CLR P3.2
CLR P3.4

;到了这里,开始测试代码
MOV 30H, #1                   ;30H:1 31H:? A:?
MOV 31H, #1                   ;30H:1 31H:1 A:?
MOV A, #1                      ;30H:1 31H:1 A:1
;判断这个中断有没有接收到数据
JNB ACC.0, LINE_XXX2   ;30H:1 31H:1 A:1         ACC.0 == 0 接着执行下一行
;到了这里                     
MOV A, 30H                  ;30H:1 31H:1 A:1
INC A ;DEBUG               ;30H:1 31H:1 A:2
CJNE A, #10, LINE_XXX3;30H:1 31H:1 A:2   A != 10 下面两句不执行
MOV A, #8                     ;不执行
SETB P3.4                      ;不执行
LINE_XXX3:                  
SUBB A, 31H                   ;30H:1 31H:1 A:1
SUBB A, #1                  ;30H:1 31H:1 A:0
JNZ LINE_XXX1               ;A==0执行下一句
SETB P3.2                     ;P3.2点亮
LINE_XXX1:
ADD A, #1                     ;30H:1 31H:1 A:2
LINE_XXX2:
SJMP $

国芯人工智能 发表于 2025-7-29 10:58:00

这段汇编代码的功能看似简单,但其中存在一些值得深入分析的细节。从整体来看,代码主要分为两部分:第一部分是控制两个LED灯的亮灭,用于验证硬件是否正常;第二部分则是对寄存器和累加器(A)的操作,并涉及条件跳转判断。

一、第一部分:LED控制

assembly
SETB P32
SETB P34
MOV R0, #0
LINEYYY1:
MOV R1, #0
LINEYYY2:
MOV R2, #0
DJNZ R2, $
DJNZ R1, LINEYYY2
DJNZ R0, LINEYYY1
CLR P32
CLR P34

该段代码通过 SETB 指令将P3口的第2位和第4位置高电平,使两个LED点亮。随后进入一个三层嵌套循环,使用R0、R1、R2作为计数器,通过 DJNZ 指令实现延时。最后通过 CLR 指令关闭LED。此部分逻辑清晰,目的是通过延时点亮再熄灭LED,验证LED是否正常工作。

需要注意的是,DJNZ 指令会先递减寄存器值,然后根据结果决定是否跳转。因此,这段延时代码的实际延时时间取决于寄存器的初始值和指令周期。若实际运行中LED未按预期亮灭,可能是延时不够或硬件连接存在问题。

二、第二部分:寄存器与累加器操作

assembly
MOV 30H, #1                   ;30H:1
MOV 31H, #1                   ;31H:1
MOV A, #1                     ;A:1
JNB ACC0, LINEXXX2         ;判断ACC0是否为0
MOV A, 30H                  ;A:1
INC A                         ;A:2
CJNE A, #10, LINEXXX3      ;比较A与10
MOV A, #8                     ;不执行
SETB P34                      ;不执行
LINEXXX3:
SUBB A, 31H                   ;A:0
SUBB A, #1                  ;A:-1

这一部分的操作较为复杂,涉及到寄存器(30H、31H)、累加器(A)以及标志位(ACC0)的处理。

1. 寄存器初始化
MOV 30H, #1 和 MOV 31H, #1 将内部RAM地址30H和31H分别赋值为1。
MOV A, #1 将累加器A设为1。

2. 条件判断 JNB ACC0, LINEXXX2
JNB ACC0 是检查累加器的最低位(即ACC0)是否为0。如果为0,则跳转到 LINEXXX2,否则继续执行下一条指令。
此处 ACC0 的初始值为0(因为A=1,其二进制表示为00000001,所以ACC0为1),因此不会跳转,程序继续执行后续指令。

3. 累加器操作
MOV A, 30H:将30H的内容(即1)复制到A,此时A=1。
INC A:A自增为2。
CJNE A, #10, LINEXXX3:比较A与10。由于A=2≠10,程序跳转至 LINEXXX3,后面的两条指令(MOV A, #8 和 SETB P34)不会执行。

4. 减法操作
SUBB A, 31H:将A减去31H的值(即1),得到A=1。
SUBB A, #1:再次减1,此时A=0,但由于是带借位的减法,若之前没有借位,则结果为0;若有借位则为FFH(即-1)。此处假设无借位,结果为0。

三、可能的疑问点分析

1. 为什么 JNB ACC0, LINEXXX2 不跳转?
   因为A被初始化为1,ACC0为1,因此不会跳转。

2. CJNE A, #10, LINEXXX3 是否合理?
   如果设计意图是判断A是否为10,那么此判断是合理的。但当前A=2,故跳转发生。

3. SUBB A, 31H 和 SUBB A, #1 的结果是否符合预期?
   从逻辑上看,两次减法后A应为0,但需注意是否涉及借位问题。

四、总结

这段代码的主要目的是测试LED的显示功能,并验证寄存器和累加器的操作逻辑。从代码结构看,逻辑清晰,但在某些条件下可能存在跳转路径未被触发的情况,建议在实际调试中使用仿真工具观察各寄存器和标志位的变化,以确保程序行为符合预期。

[本文内容由国芯人工智能辅助生成,仅供参考]

cjaizss 发表于 2025-7-29 10:59:42

最后按理,P3.2拉高,P3.4为低,可实际观测两者都为低。为何?

cjaizss 发表于 2025-7-29 11:05:03

国芯人工智能 发表于 2025-7-29 10:58
这段汇编代码的功能看似简单,但其中存在一些值得深入分析的细节。从整体来看,代码主要分为两部分:第一部 ...

最后按理,P3.2拉高,P3.4为低,可实际观测两者都为低。为何?

ercircle 发表于 2025-7-29 11:33:50

cjaizss 发表于 2025-7-29 11:05
最后按理,P3.2拉高,P3.4为低,可实际观测两者都为低。为何?
ACC不是中断,是累加器读位操作时的语法。


ACC.0 == 0 接着执行下一行,X

JNB是如果直接位未置位则跳转,这里是1,则继续执行

ercircle 发表于 2025-7-29 11:42:15


仿真发现SUBB A, 31H,这行执行后A直接变为0了




ercircle 发表于 2025-7-29 11:49:21



加一行这个:

cjaizss 发表于 2025-7-29 13:28:52

ercircle 发表于 2025-7-29 11:49
加一行这个:

是的,我发现是我把指令意思搞错了。先CLR C清除标志意思就对了。
页: [1]
查看完整版本: 这段汇编测试代码行为让我觉得诡异 | 已解决