![]() |
![]() |
#1 |
Registered User
Join Date: Apr 2015
Location: Beauharnois,Qc,Canada
Posts: 227
|
Calling assembler functions from C
Let say I write an assembler routine that does some function and I want to call it from within a C program, how would I do that with VBCC or the other most common Amiga C compiler (I don't mind using SAS or other compilers).
Anyone got an example? |
![]() |
![]() |
#2 |
Registered User
Join Date: Jan 2002
Location: Germany
Posts: 7,026
|
Make sure that the name of the assembler routine is declared as global symbol and that the name starts with a _. Then you can call it from the C program without the _.
for example: Code:
_the_answer: move.l #42,d0 rts public _the_answer Code:
#include <stdio.h> long the_answer (void); int main (void) { long a = the_answer(); printf ("the answer is %ld\n",a); } Note that if you change any register except d0 and d1, you have to restore the previous contents before your asm routine exits. You might compile a small C program with the -S option to get the assembler output from the compiler. Then you can see how a subroutine is defined in assembler. For example Code:
vc -S test.c -o test.asm Last edited by thomas; 10 November 2015 at 18:02. |
![]() |
![]() |
#3 |
Registered User
Join Date: Apr 2015
Location: Beauharnois,Qc,Canada
Posts: 227
|
Oh! Thank you!
|
![]() |
![]() |
#4 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 722
|
|
![]() |
![]() |
#5 |
Posts: n/a
|
Isn't this example a bit simplified since the_answer() doesn't take any arguments? In a normal C function call the arguments would be passed on the stack and not in CPU registers, which a typical assembler routine would prefer.
There are compiler directives you can use to make it use registers instead. In SAS/C it's something like long __asm the_answer(__register d0 long foo); (It's been a long time since I did this.. :-) ) |
![]() |
#6 | |
Registered User
Join Date: Jan 2002
Location: Germany
Posts: 7,026
|
Maybe. But it hurts more if you miss to save a needed register than if you save a scratch register.
Quote:
Here is another strongly simplified example, but this time with arguments: Code:
_add: add.l d1,d0 rts public _add Code:
#include <stdio.h> long add (__reg("d0") long a,__reg("d1") long b); int main (void) { long a = add(14,16); printf ("14 + 16 = %ld\n",a); } Code:
_add: move.l 4(sp),d0 add.l 8(sp),d0 rts public _add Code:
#include <stdio.h> long add (long a,long b); int main (void) { long a = add(14,16); printf ("14 + 16 = %ld\n",a); } Also note that arguments are put on the stack in reverse order so that they appear in memory in the correct order. This means that 4(sp) corresponds to argument a and 8(sp) to argument b. |
|
![]() |
![]() |
#7 |
Registered User
Join Date: Jul 2008
Location: Poland
Posts: 665
|
How can I link vasm compiled code with gcc ?
|
![]() |
![]() |
#8 |
Registered User
Join Date: Jun 2008
Location: somewhere else
Posts: 524
|
Afaik gcc handles objects produced with vasm (using -Fhunk in vasm command line).
|
![]() |
![]() |
#9 |
Registered User
Join Date: Jul 2008
Location: Poland
Posts: 665
|
Yes!
|
![]() |
![]() |
#10 |
Registered User
Join Date: Jun 2008
Location: somewhere else
Posts: 524
|
The advantage of working with gcc + vasm instead of gcc + as is that you can create chipmem hunk in your executable by using (in asm):
Code:
section ".data_chip",data |
![]() |
![]() |
#11 | ||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,541
|
Quote:
Quote:
Code:
section ".data_chip",data,chip |
||
![]() |
![]() |
#12 |
Registered User
Join Date: Jun 2008
Location: somewhere else
Posts: 524
|
I use gcc version 3.4.0.
No, data_c or data,chip won't work with gnu-ld, the linker uses the name of the section to relocate it to chipmem so it have to be ".data_chip",data (anything else won't work). |
![]() |
![]() |
#13 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,541
|
Ok. Didn't know that. I thought that GNU-ld would be able to evaluate the memflags, when it already supports hunk-format.
|
![]() |
![]() |
#14 |
Registered User
Join Date: Jul 2008
Location: Poland
Posts: 665
|
I can't compile this line in gcc (3.4.0):
Code:
long add (__reg("d0") long a,__reg("d1") long b); Code:
add.c:3: error: syntax error before '(' token add.c: In function `add': add.c:3: error: syntax error before string constant add.c:6: error: syntax error before '{' token Last edited by arti; 14 November 2016 at 20:10. |
![]() |
![]() |
#15 | |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 722
|
Quote:
Code:
register long a __asm("d0") |
|
![]() |
![]() |
#16 |
Banned
Join Date: Jan 2010
Location: Kansas
Posts: 1,284
|
Every compiler has its own syntax for assembler and register calling. There was an attempt years ago to make a universal syntax using macros for most of the common Amiga compilers. Vbcc was rather difficult to get working as macros don't like the characters vbcc requires for defining registers but I found a trick to get it working. It should now support GCC, vbcc, SAS/C, DICE and even the old Storm C. My contributions build on those from others. The test example is based on Thomas's example and is very simple. There is an AmigaDOS script to make the simple project using vbcc. I have not tested with other compilers so let me know if it doesn't work somewhere. Ideas for improvement are also welcome and it would be interesting to hear who came up with the original idea. See the attachment for the archive.
Edit: New version attached with GCC and vbcc tests. I believe it will only work with unofficial Amiga GCC versions like GCC 2.95.3 and 3.4.0. It was necessary to change the required syntax slightly (less readable but not too bad IMO). Needs testing and possibly fixes for other Amiga compilers. Let me know if there are problems and send me any fixes. Last edited by matthey; 15 November 2016 at 18:39. |
![]() |
![]() |
#17 |
Registered User
Join Date: Jul 2008
Location: Poland
Posts: 665
|
Great stuff matthey.
But still no go for gcc: Parse error before long a Code:
long add( REG(d0) long a, REG(d1) long b ); Last edited by arti; 15 November 2016 at 15:20. |
![]() |
![]() |
#18 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 722
|
You didn't tried, did you?
Ok, let's see. Code:
m68k-amigaos-gcc --version m68k-amigaos-gcc (GCC) 3.4.0 Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. cat foo.c long add (register long a __asm("d0"), register long b __asm("d1")); m68k-amigaos-gcc -c foo.c |
![]() |
![]() |
#19 | |
Banned
Join Date: Jan 2010
Location: Kansas
Posts: 1,284
|
Quote:
Code:
long add( register long a __asm("d0"), register long b __asm("d1") ); The macros I provided do not work for GCC (someone else created them). Maybe this is another reason why the macros did not become popular. I can get the macros to generate the correct text but the __asm("reg") part is before each variable which does not work. I may have to change how the macros work to allow a universal definition and then it still is unlikely to work with newer official GCC compilers ![]() |
|
![]() |
![]() |
#20 |
Registered User
Join Date: Jul 2008
Location: Poland
Posts: 665
|
I've tried this order ->
Code:
register __asm("d0") long a Code:
register long a __asm("d0") Last edited by arti; 15 November 2016 at 17:53. |
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Replacing OS4 functions for OS3.x | arti | Coders. C/C++ | 25 | 17 December 2018 16:03 |
functions benchmark | wawa | Coders. System | 2 | 15 April 2013 18:55 |
How do the non-i/o functions work? | mikro | project.WHDLoad | 3 | 03 November 2011 14:33 |
Lost F key Functions on WINuae startup | breadbaker | support.WinUAE | 8 | 06 December 2005 20:09 |
CD32 blue button functions differently | oldpx | support.WinUAE | 6 | 09 August 2004 13:43 |
|
|