社区
单片机/工控
帖子详情
keil 函数调用时的参数问题
genelin22
2008-07-08 10:52:53
用keil开发51的程序
写了个函数:
INT16U halSetTimer1Period(INT32U p)
{
。。。。。
}
在调用的时候参数p不能正确的传递,可是我看R4 R5 R6 R7寄存器里面的值明明是传递的那个值。
而当把参数p的类型改成两个字节的INT16U 就能正确传递了,这是什么原因呢?
谢谢指教
...全文
1014
9
打赏
收藏
keil 函数调用时的参数问题
用keil开发51的程序 写了个函数: INT16U halSetTimer1Period(INT32U p) { 。。。。。 } 在调用的时候参数p不能正确的传递,可是我看R4 R5 R6 R7寄存器里面的值明明是传递的那个值。 而当把参数p的类型改成两个字节的INT16U 就能正确传递了,这是什么原因呢? 谢谢指教
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
9 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
shuiyan
2008-07-08
打赏
举报
回复
函数体里面引用p的部分都贴出来。
既然用了INT32U,那就传个32位的数看看。然后贴编译后的汇编代码
sherlock_lai
2008-07-08
打赏
举报
回复
不能正确传递是指什么? 比如你 halSetTimer1Period(32) 传进函数里的是什么? 难道不是32?
genelin22
2008-07-08
打赏
举报
回复
可是如果用small
原来的大程序就出错了
UCOS_II.C(27): error C249: 'DATA': SEGMENT TOO LARGE
......
shuiyan
2008-07-08
打赏
举报
回复
就在项目的option里面,有Compact Small Large,默认Compact,按你所说,small就可以了。
genelin22
2008-07-08
打赏
举报
回复
[Quote=引用 6 楼 shuiyan 的回复:]
溢出了。还有堆栈设置怎么样的?
[/Quote]
恩 应该是你说的这个原因,我建工程的时候很多的都是默认设置(刚开始用keil)
不知堆栈在哪设置,估计就是堆栈设置有问题了
再次感谢
shuiyan
2008-07-08
打赏
举报
回复
溢出了。还有堆栈设置怎么样的?
fouryu
2008-07-08
打赏
举报
回复
Large模式下,默认的内存使用XData段、Small模式下默认的内存使用Data段。
从汇编语言上看你在Large模式下编译器优化产生了一个函数C?LSTXDATA: 用来处理XData参数传递的问题。使用XData的0x0000地址来保存实参。
进入Test函数首先通过C?LSTXDATA:函数将寄存器R4 R5 R6 R7的值拷贝到XData段0x0000开始的4个字节,然后开始计算p++。这个计算过程你看懂了要吐血——把刚才拷贝出去的内容再一个一个拷贝到R4 R5 R6 R7寄存器中,只是最后拷贝到R7之前先做一个加一,后面跟着做进位处理。所有的处理结束之后,再调用C?LSTXDATA:函数将寄存器R4 R5 R6 R7的值拷贝到XData段0x0000开始的4个字节。
整个流程是正确的。
你观察变量的值时要注意内存所处的段。C51是哈佛结构的CPU,这点和PC上的调试不太一样。
genelin22
2008-07-08
打赏
举报
回复
Disassembly里面的代码是这样的
发现p传递的居然是02003590(0x0000 - 0x0003里面的内容)为什么呢?
===================================================================
C:0x0000 020035 LJMP C:0035
4: void test(unsigned long p)
C:0x0003 900000 MOV DPTR,#0x0000
C:0x0006 120041 LCALL C?LSTXDATA(C:0041)
5: {
6: p++;
7:
8: }
9:
C:0x0009 900000 MOV DPTR,#0x0000
C:0x000C E0 MOVX A,@DPTR
C:0x000D FC MOV R4,A
C:0x000E A3 INC DPTR
C:0x000F E0 MOVX A,@DPTR
C:0x0010 FD MOV R5,A
C:0x0011 A3 INC DPTR
C:0x0012 E0 MOVX A,@DPTR
C:0x0013 FE MOV R6,A
C:0x0014 A3 INC DPTR
C:0x0015 E0 MOVX A,@DPTR
C:0x0016 2401 ADD A,#0x01
C:0x0018 FF MOV R7,A
C:0x0019 E4 CLR A
C:0x001A 3E ADDC A,R6
C:0x001B FE MOV R6,A
C:0x001C E4 CLR A
C:0x001D 3D ADDC A,R5
C:0x001E FD MOV R5,A
C:0x001F E4 CLR A
C:0x0020 3C ADDC A,R4
C:0x0021 FC MOV R4,A
C:0x0022 900000 MOV DPTR,#0x0000
C:0x0025 020041 LJMP C?LSTXDATA(C:0041)
10: void main(void)
11: {
12: test(0x1FFFFFFF);
C:0x0028 7FFF MOV R7,#0xFF
C:0x002A 7EFF MOV R6,#0xFF
C:0x002C 7DFF MOV R5,#0xFF
C:0x002E 7C1F MOV R4,#0x1F
C:0x0030 120003 LCALL test(C:0003)
13: while(1);
C:0x0033 80FE SJMP C:0033
C:0x0035 787F MOV R0,#0x7F
C:0x0037 E4 CLR A
C:0x0038 F6 MOV @R0,A
C:0x0039 D8FD DJNZ R0,C:0038
C:0x003B 758107 MOV SP(0x81),#0x07
C:0x003E 020028 LJMP main(C:0028)
C?LSTXDATA:
C:0x0041 EC MOV A,R4
C:0x0042 F0 MOVX @DPTR,A
C:0x0043 A3 INC DPTR
C:0x0044 ED MOV A,R5
C:0x0045 F0 MOVX @DPTR,A
C:0x0046 A3 INC DPTR
C:0x0047 EE MOV A,R6
C:0x0048 F0 MOVX @DPTR,A
C:0x0049 A3 INC DPTR
C:0x004A EF MOV A,R7
C:0x004B F0 MOVX @DPTR,A
C:0x004C 22 RET
genelin22
2008-07-08
打赏
举报
回复
写了个简单的试验程序
void test(unsigned long p)
{
p++;
}
void main(void)
{
test(0x1FFFFFFF);
while(1);
}
采用在线调试工具,memory model = large
结果进入test()中时,p的值不是1fffffff,而是一个很奇怪的的大数。
当改成模拟器调试时,该问题不存在
当改成memory model = small,时,该问题也不存在
以下是汇编代码
-----------------------------------------------------------------
; .\main.SRC generated from: main.c
; COMPILER INVOKED BY:
; C:\Keil\C51\BIN\C51.EXE main.c LARGE BROWSE DEBUG OBJECTEXTEND SRC(.\main.SRC)
NAME MAIN
?PR?_test?MAIN SEGMENT CODE
?XD?_test?MAIN SEGMENT XDATA OVERLAYABLE
?PR?main?MAIN SEGMENT CODE
EXTRN CODE (?C?LSTXDATA)
EXTRN CODE (?C_STARTUP)
PUBLIC main
PUBLIC _test
RSEG ?XD?_test?MAIN
?_test?BYTE:
p?040: DS 4
;
;
;
; void test(unsigned long p)
RSEG ?PR?_test?MAIN
_test:
USING 0
; SOURCE LINE # 4
MOV DPTR,#p?040
LCALL ?C?LSTXDATA
; {
; SOURCE LINE # 5
; p++;
; SOURCE LINE # 6
MOV DPTR,#p?040
MOVX A,@DPTR
MOV R4,A
INC DPTR
MOVX A,@DPTR
MOV R5,A
INC DPTR
MOVX A,@DPTR
MOV R6,A
INC DPTR
MOVX A,@DPTR
ADD A,#01H
MOV R7,A
CLR A
ADDC A,R6
MOV R6,A
CLR A
ADDC A,R5
MOV R5,A
CLR A
ADDC A,R4
MOV R4,A
MOV DPTR,#p?040
LJMP ?C?LSTXDATA
; END OF _test
;
; }
;
; void main(void)
RSEG ?PR?main?MAIN
main:
USING 0
; SOURCE LINE # 10
; {
; SOURCE LINE # 11
; test(0x1FFFFFFF);
; SOURCE LINE # 12
MOV R7,#0FFH
MOV R6,#0FFH
MOV R5,#0FFH
MOV R4,#01FH
LCALL _test
?C0002:
; while(1);
; SOURCE LINE # 13
SJMP ?C0002
; END OF main
END
谢谢指教 :)
keil
C语言与汇编语言混合编程
本文详细介绍了在
keil
环境下C语言与汇编语言的混合编程,包括C中嵌入汇编、无
参数
函数调用
和有
参数
传递的
函数调用
,并探讨了变量和函数接口的
问题
。在C程序中,可以使用#pragma ASM和#pragma ENDASM来插入汇编代码,而调用汇编函数
时
,
参数
会存储在特定寄存器或堆栈中。
keil
4内嵌汇编_
keil
C中嵌入汇编程序的方法
本文详细介绍了如何在
keil
C中使用内嵌汇编,包括无
参数
和有
参数
的
函数调用
。通过示例展示了如何在C文件和汇编文件间传递
参数
,以及注意的细节,如函数返回值的寄存器使用和函数名的约定。同
时
提到了C与汇编混合编程
时
的堆栈、变量共用和程序入口等
问题
。
keil
定位hardfault
当程序触发hardfault
时
,通过Log查看通用寄存器值,特别是LR。在
Keil
Disassembly窗口找到LR对应的代码位置,发现可能出
问题
的函数。通过检查
函数调用
,发现在给特定函数传递-1作为
参数
时
,导致了越界访问buf,从而引发了hardfault。
keil
5中结构体指针作为函数
参数
,无法赋值
在VSCode中,结构体指针与结构体实例操作结构体数据没有区别,但在
Keil
环境下,使用结构体指针作为函数
参数
时
遇到
问题
。在尝试初始化STM32的USART
时
,直接使用结构体实例而非指针进行赋值和初始化成功解决了
问题
。这可能涉及到C语言在不同编译器下的内存管理和
函数调用
规范差异。
如何处理
Keil
uVision5注释无法输入汉字且输入汉字变成问号的
问题
本文介绍了如何在
KEIL
中遇到汉字输入变为问号的
问题
时
,通过将EditorSettings的Encoding设置为ChineseGB2312来解决。文章详细指导了编辑Configuration页面和创建、配置项目文件的过程,包括选择设备、创建源文件、添加启动代码等。
单片机/工控
27,521
社区成员
28,799
社区内容
发帖
与我相关
我的任务
单片机/工控
硬件/嵌入开发 单片机/工控
复制链接
扫一扫
分享
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章