搜索
bottom↓
回复: 1

请问马老师:用汇编写的子程序带参数的在C中如何调用?

[复制链接]

出0入0汤圆

发表于 2005-12-31 23:19:48 | 显示全部楼层 |阅读模式
一个问题困扰我多时,就是在C中如何把参数 int 或char 传递给汇编写的子程序。比如你的书里的通用延时子程序



delay:push r16

      push r17

del1:push r16

del2:push r16

del3:dec r16

     brne del3

     pop r16

     del r16

     brne del2

     pop r16

     dec r16

     brne del1

     pop r16

     ret

希望马老师及各位大侠不吝赐教,谢谢!

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2006-1-22 14:39:52 | 显示全部楼层
使用不同的C平台,调用的方式有些不同,并且汇编子程序要做稍微的变化,以适合C的调用以及传递参数。但总的讲,比使用KEIL(8051)要方便。



下面给出在CVAVR和ICC中的例子,这些都在它们的在线帮助中。



------------------------------------------------------

CVAVR的调用说明:

The following example shows how to access functions written in assembly language from a C program:



// function in assembler declaration

// this function will return a+b+c

#pragma warn- // this will prevent warnings

int sum_abc(int a, int b, unsigned char c) {

#asm

    ldd   r30,y+3 ;R30=LSB a

    ldd   r31,y+4 ;R31=MSB a

    ldd   r26,y+1 ;R26=LSB b

    ldd   r27,y+2 ;R27=MSB b

    add   r30,r26 ;(R31,R30)=a+b

    adc   r31,r27

    ld    r26,y   ;R26=c

    clr   r27     ;promote unsigned char c to int



    add   r30,r26 ;(R31,R30)=(R31,R30)+c

    adc   r31,r27

#endasm

}

#pragma warn+ // enable warnings



void main(void) {

int r;

// now we call the function and store the result in r

r=sum_abc(2,4,6);

}



The compiler passes function parameters using the Data Stack.

First it pushes the integer parameter a, then b, and finally the unsigned char parameter c.

On every push the Y register pair decrements by the size of the parameter (4 for long int, 2 for int, 1 for char).



For multiple byte parameters the MSB is pushed first.

As it is seen the Data Stack grows downward.

After all the functions parameters were pushed on the Data Stack, the Y register points to the last parameter c, so the function can read its value in R26 using the instruction: ld r26,y.

The b parameter was pushed before c, so it is at a higher address in the Data Stack.

The function will read it using: ldd r27,y+2 (MSB) and ldd r26,y+1 (LSB).

The MSB was pushed first, so it is at a higher address.



The a parameter was pushed before b, so it is at a higher address in the Data Stack.

The function will read it using: ldd r31,y+4 (MSB) and ldd r30,y+3 (LSB).



The functions return their values in the registers (from LSB to MSB):

    R30 for char and unsigned char

    R30, R31 for int and unsigned int

    R30, R31, R22, R23 for long and unsigned long.



So our function must return its result in the R30, R31 registers.



After the return from the function the compiler automatically generates code to reclaim the Data Stack space used by the function parameters.



The #pragma warn- compiler directive will prevent the compiler from generating a warning that the function does not return a value.

This is needed because the compiler does not know what it is done in the assembler portion of the function.





------------------------------------------------------

在ICC中比较复杂些,但使用INLINE方式汇编时还是比较方便的:

Besides writing assembly functions in assembly files, inline assembly allows you to write assembly code within your C file. (Of course, you may use assembly source files as part of your project as well.) The syntax for inline assembly is:



asm("<string>");



Multiple assembly statements can be separated by the newline character
. String concatenations can be used to specify multiple statements without using additional asm keywords. To access a C variable inside an assembly statement, use the %<name> format:



register unsigned char uc;

asm("mov %uc,R0
"

    "sleep
");



Any C variable can be referenced this way (excluding C goto labels). If you use an assembly instruction that requires a CPU register, then you must use the register storage class to force a local variable to be allocated in a CPU register.

In general, using inline assembly to reference local registers is limited in power: it is possible that no CPU registers are available if you have declared too many register variables in that function. In that case, you would get an error from the assembler. There is also no way to control allocation of register variables, so your inline instruction may fail. For example, using the ldi instruction requires the register to be one of the 16 upper registers, but there is no way to request that using inline assembly. There is also no way to reference the upper half of an integer register.



Inline assembly may be used inside or outside of a C function. The compiler indents each line of the inline assembly for readability. Unlike the AVR assembler, the ImageCraft assembler allows labels to be placed anywhere (not just at the first character of the lines in your file) so you may create assembly labels in your inline assembly code. You may get a warning on asm statements that are outside of a function. You may ignore these warnings.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 01:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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