找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4178|回复: 91
收起左侧

请教各位大神一个汇编语言堆栈大小计算的问题

[复制链接]
ID:227818 发表于 2022-7-12 06:34 | 显示全部楼层 |阅读模式
我有一个主程序A(是51单片机的汇编),在STC 8H上跑,这个主程序A调用了子程序A1,A1又调用了A2,A2又调用了A3,即A->A1->A2->A3。中断用了5个,可以定义成中断B,C,D,E,F。其中中断B,C是高级中断,D,E,F是低级中断。所有中断中都是PUSH ACC,PUSH PSW,没有再PUSH其他寄存器,出中断时POP PSW ,POP ACC。中断B中,调用了子程序B1,B1又调用了B2即B-B1->B2。C中断中没有调用其他子程序。D中断中调用了子程序D1,D1又调用了D2,即D->D1-D2。E中断中调用了子程序E1,E1又调用了E2,E2又调用了E3,即E->E1->E2-E3。所有子程序都是简单的对单片机的端口进行操作,即置高或低,子程序没有用堆栈传递参数。按照我的理解,考虑一个最复杂的情况,主程序在调用A3时,堆栈用了6个字节,这时发生E中断,E中断在调用E3时,堆栈用了8个字节,这是发生B中断,在B中断调用B2时,堆栈用了6个字节,这样堆栈最多用20个字节就可以了,但在实际情况中,单片机不时会死机.这个程序原先不是我写的,我不过做了一点修改,即在中断E中加了一个子程序E3。以前堆栈留的比较小,只有20个字节,后来我又找了几个加上了,但还是不大。现在我怀疑是堆栈溢出了,请问我堆栈大小的计算对吗?衷心感谢
回复

使用道具 举报

ID:887371 发表于 2022-7-12 12:03 | 显示全部楼层
1.51的任何子程序都需要通过堆栈传递PC值,最少2字节。
2.51的中断子程序通过堆栈传递PC、ACC、PSW ,最少4字节。
3.中断内部调用子程序算情形1,最少2字节。

你的代码有2级中断调用,情形1调用算6级,所以最少20字节(2*4+6*2)。
但上述是最理想的情况。我们一般按10级情形1算,但情形1算5字节,预留50字节堆栈。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:401564 发表于 2022-7-12 12:26 | 显示全部楼层
8051是软件堆栈,如果不是刻意去填满它,堆栈基本上是不会有问题的
卡死的问题不一定是堆栈的问题,可能是中断太多,而且中断触发间隔时间太短
比如说:
1,ADC中你调用了某个子程序,ADC执行的总时长是5mS,ADC中断你又设定成最高优先等级,而ADC中断间隔是1mS
2,定时器中断是2mS的
那么,这个程序就一直在ADC和定时器之间运行了,主程序基本是不会执行的

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:227818 发表于 2022-7-12 14:21 | 显示全部楼层
datouyuan 发表于 2022-7-12 12:03
1.51的任何子程序都需要通过堆栈传递PC值,最少2字节。
2.51的中断子程序通过堆栈传递PC、ACC、PSW ,最少 ...

谢谢您的回复,我算的是最多需要20字节,您算的最少需要20字节
我是这样理解的同为高级的2个中断B,C,同一时刻只能有一个中断响应,C中断响应,堆栈占用2个字节,B中断响应,最多占用6个字节,所以按B中断记,D,E,F三个低级中断,它们三个同一时刻只有1个被CPU响应,主贴中忘记说了,F中断内没有子程序,按子程序调用最深的E中断算,低级中断最多需要8个字节,主程序中子程序调用最多需要6个字节,这样需要20个字节就可以了。按照您的计算,我肯定是哪里理解错了,错在那里,麻烦您再说一下,我在这方面是半路出家,有些方面理解不透,谢谢。
回复

使用道具 举报

ID:227818 发表于 2022-7-12 14:28 | 显示全部楼层
Y_G_G 发表于 2022-7-12 12:26
8051是软件堆栈,如果不是刻意去填满它,堆栈基本上是不会有问题的
卡死的问题不一定是堆栈的问题,可能是中 ...

谢谢您的回复,我明白了您的意思,您是说,中断触发间隔的时间短,而中断本身执行的时间长,结果就是CPU在中断之间运行,一个中断执行完,马上又去响应另一个中断,然后又去响应前一个中断,没有时间去执行主程序,我按您的思路拿示波器跟踪下,看看每一个中断需要多少时间。
回复

使用道具 举报

ID:1006814 发表于 2022-7-12 15:00 | 显示全部楼层
每次中断,自动入栈一个PC寄存器,具体几个字节我忘了,然后中断返回的时候再自动出栈,楼主没考虑这个,所以可能会乱。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:227818 发表于 2022-7-12 15:24 | 显示全部楼层
hb_lhw 发表于 2022-7-12 15:00
每次中断,自动入栈一个PC寄存器,具体几个字节我忘了,然后中断返回的时候再自动出栈,楼主没考虑这个,所 ...

您说的应该是程序寄存器,也就是PC寄存器,它是16位的,占用2个字节,按说我已经考虑到了。
回复

使用道具 举报

ID:227818 发表于 2022-7-12 15:27 | 显示全部楼层
datouyuan 发表于 2022-7-12 12:03
1.51的任何子程序都需要通过堆栈传递PC值,最少2字节。
2.51的中断子程序通过堆栈传递PC、ACC、PSW ,最少 ...

我刚才又想到,是不是中断嵌套时,堆栈需要消耗更多的字节?中断嵌套时堆栈消耗的字节是怎样计算的?
回复

使用道具 举报

ID:227818 发表于 2022-7-12 15:44 | 显示全部楼层
本帖最后由 newlined 于 2022-7-12 15:47 编辑
Y_G_G 发表于 2022-7-12 12:26
8051是软件堆栈,如果不是刻意去填满它,堆栈基本上是不会有问题的
卡死的问题不一定是堆栈的问题,可能是中 ...

您好,我刚才拿示波器跟踪了一下,一共5个中断,2个中断是1毫秒一次,一个外部中断是20毫秒到100毫秒一次,这3个1个请问-中断的时间在5微妙到10微妙之间,应该没有问题。还有一个是30毫秒1次,执行时间是10微秒,也没有问题,执行时间比较长的是一个掉电中断,是高级中断,执行时间10毫秒,这个中断执行完就不再执行其他语句了,单片机就等着掉电了。按说也不影响主程序的运行
回复

使用道具 举报

ID:624769 发表于 2022-7-12 16:25 | 显示全部楼层
是不是堆栈大小的问题, 用KEIL 编译后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我现在好奇的是,你确定是堆栈问题? 你那么多中断 你居然   都是只 PUSH ACC 和 PSW 的? 你不用 R0~R7 的? 不用 B 的?  不用 DPTR 的? 这些只要有一个,你该PUSH 的没有PUSH 都会有可能造成发生过 中断后,程序出现错误,最终跑飞。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:401564 发表于 2022-7-12 16:56 | 显示全部楼层
newlined 发表于 2022-7-12 14:28
谢谢您的回复,我明白了您的意思,您是说,中断触发间隔的时间短,而中断本身执行的时间长,结果就是CPU ...

大概就是这么个意思了
也就是说程序是在中断之间来回跑的
主程序几乎没有执行的时间
为什么要在中断中执行那么多功能呢?能不能放在主程序执行呢?
回复

使用道具 举报

ID:227818 发表于 2022-7-12 17:03 | 显示全部楼层
Y_G_G 发表于 2022-7-12 16:56
大概就是这么个意思了
也就是说程序是在中断之间来回跑的
主程序几乎没有执行的时间

这个程序是20年前别人编写的,我现在接手维护,整个程序还没有吃透。
回复

使用道具 举报

ID:227818 发表于 2022-7-12 17:13 | 显示全部楼层
Y_G_G 发表于 2022-7-12 16:56
大概就是这么个意思了
也就是说程序是在中断之间来回跑的
主程序几乎没有执行的时间

大约1小时前回复过,不知道回帖为什么没有了。今天下午我拿示波器跟踪了各个中断的执行时间,有2个是1毫秒1次的中断,执行时间在10微妙左右,1个是30毫秒的中断,执行时间是10微妙多一点,一个外部中断,20毫秒到100毫秒一次,执行时间在8微妙左右,应该都可以,不会引起主程序执行时间的不足,一个掉电中断,是高级中断,执行时间10毫秒,这个按说也不影响主程序的运行,因为这个中断执行完,就等着掉电了,不再执行其他语句了。
回复

使用道具 举报

ID:227818 发表于 2022-7-12 17:18 | 显示全部楼层
188610329 发表于 2022-7-12 16:25
是不是堆栈大小的问题, 用KEIL 编译后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我现在好奇 ...

这个程序是20年前别人写的,我接手维护,小改下,不好动架构。
回复

使用道具 举报

ID:887371 发表于 2022-7-12 17:23 | 显示全部楼层
newlined 发表于 2022-7-12 14:21
谢谢您的回复,我算的是最多需要20字节,您算的最少需要20字节
我是这样理解的同为高级的2个中断B ...
考虑一个最复杂的情况,主程序在调用A3时,堆栈用了6个字节,这时发生E中断,E中断在调用E3时,堆栈用了8个字节,这是发生B中断,在B中断调用B2时,堆栈用了6个字节,这样堆栈最多用20个字节就可以了

A到A3,是函数调用3级,最少6字节。
E中断,是中断函数调用,最少4字节。
E到E3,是函数调用3级,最少6字节。
B中断,是中断函数调用,最少4字节。
B到B2,是函数调用2级,最少4字节。
最少24字节。

不需要按上述计算,堆栈就是按函数调用深度和中断函数调用深度估算。
函数调用深度8级,最少占用16(2*8)字节。
中断函数调用深度2级,最少占用8(4*2)字节。
我提到的3点原则只考虑了PCH PCL ACC PSW的保存、恢复,是最低要求的情形。有些应用还要考虑DPTR、B、R0~R7的保存、恢复,所以堆栈需求会明显大于24个字节。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:887371 发表于 2022-7-12 17:35 | 显示全部楼层
C51中断中使用函数是很不好的习惯。
你把中断中的函数改成不是函数,以代码空间换时间和RAM。
应该能解决问题。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:401564 发表于 2022-7-12 18:20 | 显示全部楼层
newlined 发表于 2022-7-12 17:13
大约1小时前回复过,不知道回帖为什么没有了。今天下午我拿示波器跟踪了各个中断的执行时间,有2个是1毫 ...

所谓"死机"和中断无法跳出,这不过是推测而已,说不定可能就是其它的小问题而已
汇编是很容易出问题的
如果说是以前的代码是可以量产的,就说明以前的代码是没有问题的
重点看你的代码会影响到哪些
如果不是什么商业机密,就把完整代码上传,大家一看就知道了
回复

使用道具 举报

ID:227818 发表于 2022-7-13 13:32 | 显示全部楼层
188610329 发表于 2022-7-12 16:25
是不是堆栈大小的问题, 用KEIL 编译后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我现在好奇 ...

您好,以前的程序就是没有对DPTR保护。看了您的发言后,我看了下程序,里边的确用了DPTR,不知道为什么程序还可以运行。工作寄存器的4个区,有1个区是2个低级中断公用的,这2个中断不会同时响应,只用了R0和R1,每次用之前,都要先赋值,访问间接寻址的空间,所以不会冲突。B寄存器也用了,不知道为什么没有保护。这个程序大几千行,没有文字的介绍资料,注释也很少,估计不止一人维护过.我还远没有吃透.
回复

使用道具 举报

ID:624769 发表于 2022-7-13 13:44 | 显示全部楼层
newlined 发表于 2022-7-13 13:32
您好,以前的程序就是没有对DPTR保护。看了您的发言后,我看了下程序,里边的确用了DPTR,不知道为什么程 ...

程序没吃透的前提下, 最不变应万变的做法,就是中断里用了了什么, 进入中断前就 PUSH什么, 出中断前 POP什么, 这是最笨,但也是最稳妥的办法。 等到吃透之后,可以选择性的 PUSH 和 POP

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:227818 发表于 2022-7-13 13:47 | 显示全部楼层
datouyuan 发表于 2022-7-12 17:35
C51中断中使用函数是很不好的习惯。
你把中断中的函数改成不是函数,以代码空间换时间和RAM。
应该能解决 ...

您好,您这一说,我意识到一个问题,函数重入,这个程序编译时曾经出过这个警告,后来我把一个函数复制了一份,另起了一个名字,供不同的子程序还是中断调用,现在是不是还有这个问题?在keil c中也不能这么用吗?
回复

使用道具 举报

ID:887371 发表于 2022-7-13 15:12 | 显示全部楼层
newlined 发表于 2022-7-13 13:47
您好,您这一说,我意识到一个问题,函数重入,这个程序编译时曾经出过这个警告,后来我把一个函数复制了 ...

一般的C51函数是不支持再入的。
一个函数复制了一份,另起了一个名字

可以这样解决(这个函数内部不能有函数),但你必须确保业务逻辑不会有问题。

中断调用的函数一般只被中断调用,所以没有必要写成函数。

评分

参与人数 1黑币 +15 收起 理由
newlined + 15

查看全部评分

回复

使用道具 举报

ID:227818 发表于 2022-7-13 15:42 | 显示全部楼层
datouyuan 发表于 2022-7-12 17:35
C51中断中使用函数是很不好的习惯。
你把中断中的函数改成不是函数,以代码空间换时间和RAM。
应该能解决 ...

您说的对,开始我并没有理解您的意思,刚才看中断中的函数,我想到,假设在中断中,我使用了R0,然后调用函数,在函数中我又使用了R0,从函数返回后,R0的值肯定变了.好在我用R0都是用来访问间接寻址的地址,随用随赋值,要是用R0保存某个数据的话,调用函数前,可不可以PUSH到堆栈,调用函数后再POP?
回复

使用道具 举报

ID:887371 发表于 2022-7-13 15:52 | 显示全部楼层
newlined 发表于 2022-7-13 15:42
您说的对,开始我并没有理解您的意思,刚才看中断中的函数,我想到,假设在中断中,我使用了R0,然后调用 ...

当然可以。但这又会增加堆栈需求。
汇编代码要自己考虑如何保护现场,恢复现场。

C51编译器能根据上下文,自动做好保护现场,恢复现场。
好在我用R0都是用来访问间接寻址的地址,随用随赋值

你这种做法没有用。这个操作不是原子操作,中断会发生在操作中间,发生中断后,不能恢复现场。
回复

使用道具 举报

ID:227818 发表于 2022-7-13 16:11 | 显示全部楼层
datouyuan 发表于 2022-7-13 15:52
当然可以。但这又会增加堆栈需求。
汇编代码要自己考虑如何保护现场,恢复现场。

您是说中断自己不能恢复现场,需要人为的PUSH,POP来恢复现场?而函数调用,C51的编译器可以调用函数时,用堆栈保存PC的值,调用完,函数执行到RET,PC的值自动恢复,其他寄存器的值也自动恢复?
回复

使用道具 举报

ID:887371 发表于 2022-7-13 17:12 | 显示全部楼层
newlined 发表于 2022-7-13 16:11
您是说中断自己不能恢复现场,需要人为的PUSH,POP来恢复现场?而函数调用,C51的编译器可以调用函数时, ...

只有PC值能自动恢复,其它值得恢复要靠软件操作。
回复

使用道具 举报

ID:227818 发表于 2022-7-13 17:22 | 显示全部楼层
是这样,明天我仿真下,再仔细领会您的意思。
回复

使用道具 举报

ID:624769 发表于 2022-7-13 18:22 | 显示全部楼层
newlined 发表于 2022-7-13 16:11
您是说中断自己不能恢复现场,需要人为的PUSH,POP来恢复现场?而函数调用,C51的编译器可以调用函数时, ...

你是不是理解 混了?
你如果写汇编的话, 是不用C51 编译器, 用A51 编译器的。
C51 的话, 函数是可以做成重入函数的, (即便他编译报了有重入风险)。
而 A51 的话,你只要用好了 PUSH POP 函数也可以做成  重入的。比如: 被调用函数,用到 R0, 你只要函数入口 PUSH AR0, 出口 POP AR0  那么,这个函数,你中断调用了,一样现场会被保护。
回复

使用道具 举报

ID:227818 发表于 2022-7-14 08:26 | 显示全部楼层
Y_G_G 发表于 2022-7-12 18:20
所谓"死机"和中断无法跳出,这不过是推测而已,说不定可能就是其它的小问题而已
汇编是很容易出问题的
如 ...

您好,这个可能不方便贴出,随说是20年的程序,但老板交代过。
经 188610329大神提醒,我DPTR没有保护造成的,但这个寄存器以前就没有保护,可能是我修改了程序,不保护不行了。汇编是很麻烦,要面面俱到。、z*cx您好,这个可能不方便贴出,随说是20年的程序,但老板交代过。
回复

使用道具 举报

ID:227818 发表于 2022-7-14 08:39 | 显示全部楼层
您好,是这样,程序是汇编的,扩展名是ASM,但是在KEIL C下编译的,我注意到一个问题,在KEIL C下新建一个汇编工程,它的扩展名是A51,我怀疑这个程序最开始不是在KEIL C下编译的,后来转到KEIL C下,KEIL C内部是不是有A51的编译器?
回复

使用道具 举报

ID:227818 发表于 2022-7-14 08:45 | 显示全部楼层
Y_G_G 发表于 2022-7-12 18:20
所谓"死机"和中断无法跳出,这不过是推测而已,说不定可能就是其它的小问题而已
汇编是很容易出问题的
如 ...

您好,刚才回复过,提交时不小心按错了键,出现了乱码,可能审核不通过。
这个程序,虽说是20年前的了,但老板有交代,不方便贴出。
经188610329 大神提醒,我怀疑是DPTR没有保护造成的,我补充了一些代码,可能是不保护不行了。
回复

使用道具 举报

ID:227818 发表于 2022-7-14 09:57 | 显示全部楼层
datouyuan 发表于 2022-7-13 17:12
只有PC值能自动恢复,其它值得恢复要靠软件操作。

刚才仿真了下,只看的R0,在中断下,给它赋一个值,比如说5,然后调用一个函数,在函数中对R0修改为8,函数执行完后,再返回调用它的那个中断,发现R0的值还是8,看来在中断中使用函数真不是一个好的习惯。
回复

使用道具 举报

ID:883242 发表于 2022-7-14 19:44 | 显示全部楼层
你的软件用到了idata了吗?
回复

使用道具 举报

ID:624769 发表于 2022-7-14 19:55 | 显示全部楼层
newlined 发表于 2022-7-14 08:39
您好,是这样,程序是汇编的,扩展名是ASM,但是在KEIL C下编译的,我注意到一个问题,在KEIL C下新建一个 ...

KEIL 就是编译器,
KEIL C51 是在KEIL 下的 51单片机 用的C语言
KEIL A51 是在KEIL 下的 51单片机 用的A语言
你既然是 用的汇编,后缀还是 ASM 就肯定是用的 A51 编译,怎么可能用 C51编译?
两者编译方式完全不一样, KEIL中的提示也不一样,一个是: compiling xxxxxxx.C...  一个是:assembling xxxxxxx.ASM...
回复

使用道具 举报

ID:624769 发表于 2022-7-14 20:06 | 显示全部楼层
newlined 发表于 2022-7-14 09:57
刚才仿真了下,只看的R0,在中断下,给它赋一个值,比如说5,然后调用一个函数,在函数中对R0修改为8,函 ...

如果,你进入中断,用的是不同的寄存器组, 那么,你对 R0 的操作,是不会影响 主程序的 R0的,因为,此 R0 不是 彼R0,  相对于这个问题,我反而觉得,你应该是 对某些寄存器的 现场保护没有做好。你新加的内容才是关键。
而且,你说的部分内容,我觉得非常困惑,“以前堆栈留的比较小,只有20个字节,后来我又找了几个加上了,但还是不大。” 你这个  只有20字节是什么来的? 又找了几个加上 是怎么加的? 正常情况下, 一般分配完内存地址后, 我们就在  内存末尾 打上 Stack,作为堆栈的起点,赋值给SP, 假定SP 为 80H, 那么 从80H 往后 到 0FFH 相当于都是 堆栈用的。 所以不存在原来 堆栈只有多少,然后你还“找了几个”的情况存在。 所以,你描述的这个情况,到底是什么情况?
回复

使用道具 举报

ID:401564 发表于 2022-7-14 20:43 | 显示全部楼层
newlined 发表于 2022-7-14 08:26
您好,这个可能不方便贴出,随说是20年的程序,但老板交代过。
经 188610329大神提醒,我DPTR没有保护造 ...

DPTR,R0,R1什么的,你在多个地方用到了,就进行保护,如果用不到就不用管
汇编子程序的原则是你在调用的时候,如果在其它地方你也用到某个地址的RAM.那就进行保护,每个子程序都要保护
常用的就是R0R1之类,比如DELAY:               
        PUSH R0        PUSH R1
        MOV R0,#100
        MOV R1,#100
NEXT:
        DJNZ R1,NEXT
        DJNZ R0,NEXT
        POP R1
        POP R0
        RET

这就是一个延时程序,这样的话,你在其它的程序中包括中断,再使用R0R1,也同样的PUSH,POP,那么这个程序就不会出问题
假设你整个完整的程序中,只有这一个地方用到R0R1,那么,这个PUSH,POP就是多余的
还有R0-R7这几个地址,默认的情况下,在整个程序地址是固定的,你在任何一个地方修改了R0-R7其中一个的值,它在其它地方的也是会改变的
假设你延时中用到了R0,中断中也用到R0,那么当延时程序被中断打断之后,如果不用PUSH,POP保护R0的话,等到中断中修改了R0之后
RETI返回之后,R0的值就是中断中最后操作的值,那么,你这个延时程序就出错了
你不要都是想着堆栈满不满的,基本不会的,完全可以先不管堆栈的大小问题
专注找你自己代码的问题
回复

使用道具 举报

ID:624769 发表于 2022-7-14 21:07 | 显示全部楼层
Y_G_G 发表于 2022-7-14 20:43
DPTR,R0,R1什么的,你在多个地方用到了,就进行保护,如果用不到就不用管
汇编子程序的原则是你在调用的时 ...

R0~R7 属于 通用寄存器, 是不能PUSH的。
如果是完全自己写的代码,配合USING 可以用 PUSH AR0~AR7 方式来PUSH 但是,如果不是自己的代码,而4组寄存器 一直轮换在用的话,非常不好处理。
所以,还是比较建议楼主多注重一下,改了部分的代码,到底涉及到哪些东西,针对性的处理一下,而不是去动那些既存的,由来已久的代码。
简易楼主,全程序  查找一下, "MOV  PSW,#"   看看具体用了几组 通用寄存器,为了影响最小化,假定,之前只用了 3组寄存器,建议楼主加的部分代码全都用 第四组 通用寄存器,这样,可以把影响降到最低。
回复

使用道具 举报

ID:883242 发表于 2022-7-14 21:41 | 显示全部楼层
函数的好处是可以复用,一处定义多处调用,节约程序空间。

但是对于大多数8位单片机编译器,包括C51,没有按照标准c语言的做法——在进入函数的时候在堆栈上临时分配局部变量(具体做法可以看《数据结构》关于递归的那一部分),因为8位机间接寻址指令和空间非常有限,按标准c语言的做法,最后生成的机器码会非常庞大,占用的RAM空间也非常多,对本来就很少的资源造成巨大浪费。

C51的做法是对函数调用关系进行分析,然后静态分配变量,以楼主的问题为例A->A1->A2->A3,那么A的局部变量可能是27H~29H,A1的局部变量占用2AH~2FH,A2的局部变量占用30H~35H,A3的局部变量占用36H以后空间。这种做法导致中断调用的函数是无法复用的!比如中断B调用了函数B1,B1的局部变量占用33H这个空间,那么如果主程序调用B1,局部变量在运算过程中发生了中断,中断B1修改了局部变量,那么中断结束后,回到主程序,局部变量33H的内容被修改了,那么主程序显然就会执行错误。同样的原因,不仅主程序不能调用B1,其他中断C、D也不能调用B1!!!这个函数B1是中断B专用的。

综上所述,使用函数,可以复用的优点在中断这里不存在!在中断中调用函数只有各种各样的缺点,一点好处都没有,楼主为什么要这么做?
回复

使用道具 举报

ID:401564 发表于 2022-7-14 22:01 | 显示全部楼层
188610329 发表于 2022-7-14 21:07
R0~R7 属于 通用寄存器, 是不能PUSH的。
如果是完全自己写的代码,配合USING 可以用 PUSH AR0~AR7 方式 ...

好久不用汇编了,忘记了
回复

使用道具 举报

ID:227818 发表于 2022-7-15 10:58 | 显示全部楼层
Hephaestus 发表于 2022-7-14 19:44
你的软件用到了idata了吗?

您好,用到了
回复

使用道具 举报

ID:227818 发表于 2022-7-15 11:08 | 显示全部楼层
Hephaestus 发表于 2022-7-14 21:41
函数的好处是可以复用,一处定义多处调用,节约程序空间。

但是对于大多数8位单片机编译器,包括C51,没 ...

您好,在中断中有十几行语句,用了几次,早先我不知道函数调用会产生一些列的问题,就把它们写成了函数.前边datouyuan大神也已经指出了.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表