Mixing C and asm

SGDK only sub forum

Moderator: Stef

Post Reply
tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Mixing C and asm

Post by tryphon » Sat Jan 16, 2016 11:03 pm

Sorry if it has already been asked, but I didn't find :)

My game engine is too slow. I'll try to optimize algorithms if possible, but I'm more and more convinced that it won't be enough and that I'll have to code some parts in asm.

I never tried to mix asm and C, and I didn't find examples about how it works. So if someone could show me on simple examples how to do basic stuff in the following situations :

Situation 1 : I want to define a function scmurtz which takes 1 integer and returns 42 if it's greater then 10, or 31 if lower.

Code: Select all

int schmurtz(int a) {
    ...
}
What asm code to put in place of dots ?

Situation 2 : I have an already coded (in C) schmurtz function that takes 1 integer and returns one integer. I want to code a zorglub function that takes 1 integer and returns 1 + the result of schmurtz.

Code: Select all

int zorglub(int a) {
    ...
}
Same question.

I think these situations cover most of my needs. I already know the parameters are passed with the stack, but I don't know what to do with output values, nor how to call an external C function.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mixing C and asm

Post by Stef » Sun Jan 17, 2016 9:09 pm

You can mix C & asm but if the plan is to put all method's code in assembly then just why not writing the whole method in an assembly file (.s) then ?
That is really better than mixing C & asm with the awful syntax involved for that...
SGDK does that and you can look as some .s file (as tools_a.s for instance) to see how it's done.
Something to know about the C convention when you call a (asm) method :
- parameters are stored on stack (A7) and always as dword (32 bits) even if parameter is char or short.
- D0, D1, A0, A1 can be freely modified by the method.
- D2-D7 and A2-A6 should be preserved (A7 is the stack so you will always preserve it).
- D0 contains return value when needed.

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Mixing C and asm

Post by tryphon » Sun Jan 17, 2016 10:08 pm

Stef wrote:You can mix C & asm but if the plan is to put all method's code in assembly then just why not writing the whole method in an assembly file (.s) then ?
Because I didn't know it was easier :)
That is really better than mixing C & asm with the awful syntax involved for that...
And I didn't know it was so awful :)
SGDK does that and you can look as some .s file (as tools_a.s for instance) to see how it's done.
Something to know about the C convention when you call a (asm) method :
- parameters are stored on stack (A7) and always as dword (32 bits) even if parameter is char or short.
- D0, D1, A0, A1 can be freely modified by the method.
- D2-D7 and A2-A6 should be preserved (A7 is the stack so you will always preserve it).
So, if I understood correctly, d0 is the return value ?

For situation 1, it would be something like :

Code: Select all

	.global schmurtz

schmurtz:
	movem.l	(a7), d1
	moveq	#42, d0
	cmpi.l	#10, d1
	bge		.exit
	moveq	#31, d0
.exit:
	rts
And then I can use schmurtz(18); in my C code ?
Also, why are labels prefixed by a dot ? To make them local ?

I saw this line in vdp_pal (but not in tools):

Code: Select all

    .type   VDP_getPaletteColors, @function
What does it mean ? Can I define something else with the @syntax ?

For situation 2, how do I call an already defined C function ? Simple jsr ? And for variables / constants defined elsewhere ?

Something like that :

Code: Select all

zorglub:
	jsr	schmurtz
	addq	#1, d0
	rts
If schmurtz prototype is in a foo.h file, how do I tell the compiler ? Is it necessary ?

Sorry, it's a lot of questions, but I need to make this clear...

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mixing C and asm

Post by Stef » Sun Jan 17, 2016 10:26 pm

tryphon wrote: And I didn't know it was so awful :)
Believe me, it's insane :p
So, if I understood correctly, d0 is the return value ?
Oh yeah, i forgot about that one (i just edited my reply), D0 contains return value when needed.
For situation 1, it would be something like :

Code: Select all

	.global schmurtz

schmurtz:
	[b]move.l[/b]	(a7), d1
	moveq	#42, d0
	cmpi.l	#10, d1
	bge		.exit
	moveq	#31, d0
.exit:
	rts
And then I can use schmurtz(18); in my C code ?
Yeah, that is exactly that :) Note that i exchanged you movem with move as movem is useful for multiple moves ;)
Now you just need to declare the method in a .h file as:

Code: Select all

void schumurtz(u32 value);
And that is, your compiler will know the method exist somewhere so you can use it in your C code and don't worry about undefined method ;)
Also, why are labels prefixed by a dot ? To make them local ?
Yeah, handy to not accidentally use an already existing label / variable / function name. As you can see all these are basically the same: just an address with a name ;)
I saw this line in vdp_pal (but not in tools):

Code: Select all

    .type   VDP_getPaletteColors, @function
What does it mean ? Can I define something else with the @syntax ?
Definitely not needed, that is tips for the assembler but is completely useless (at least i don't know where it is used).
The type is defined on your own depending how you declare it in the .h file.
For instance you could declare schumurtz as

Code: Select all

extern u32 schumurtz;
so C code will then see schumurtz as a u32 variable.
For situation 2, how do I call an already defined C function ? Simple jsr ? And for variables / constants defined elsewhere ?

Something like that :

Code: Select all

zorglub:
	jsr	schmurtz
	addq	#1, d0
	rts
Yeah you just call them with their name :
jsr myFunction for function
move var, d0 for variable

You can see in the maths3d_a.s file, i directly access the 'context3D' variable declared in math3d.c freely.
The linker will resolve all the symbols and if they exists you should not have any troubles.
Hope that make things clearer for you !

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Mixing C and asm

Post by tryphon » Sun Jan 17, 2016 10:31 pm

Thanks, it's all clear :)

Just one last question, but it's not an important one : is there a way to use the "d0", "a1" syntax rather than "%d0", "%a1" (just because I'm more used too, and "%" needs 2 fingers to be typed :) ) ?

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mixing C and asm

Post by Stef » Sun Jan 17, 2016 11:20 pm

You need to add the "--register-prefix-optional" switch to the compiler, just edit the SGDK makefile for that.
Note that you won't be able to use C variable having same name as 68000 register then :p

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Mixing C and asm

Post by tryphon » Mon Jan 18, 2016 8:59 am

Thanks a lot!
I never call my variables a1 or d0 ! (needs to check :) )

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Re: Mixing C and asm

Post by r57shell » Tue Jan 19, 2016 5:52 pm

As I see in code posted here... you're using syntax without "%". How do you use them?
When I tried to compile assembly in SGDK, it required gcc syntax (actually GNU syntax).
Oh, I see a bit above answer on this question. Sorry, I'm slowpoke :oops:

Ok, to avoid deleting this post, I'll ask other question.
Is there way to define local lable as in asm68k?
In asm68k label that starting from @ is representing local label, and you can have between each two normal labels, multiple local labels.
For example, in any function you can have @ret label. But if you define label starting from dot, or even .L (dot L), then you can't have multiple such labels in same assembly file. It leads to annoying mess with counting of used labels, and increasing length of labels. :(
Image

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mixing C and asm

Post by Stef » Tue Jan 19, 2016 9:06 pm

Of course you have local label, you need to declare them with dot in AS where it's declared with @ in asm68k. Normal label are just plain label without starting dot character in AS ;)

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Re: Mixing C and asm

Post by r57shell » Wed Jan 20, 2016 12:04 am

but two labels ".ret" leads to error of "already defined"... :(
Image

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mixing C and asm

Post by Stef » Wed Jan 20, 2016 9:22 am

Err you're right ! Just checking my code and i can see i never use duplicated labels... I though prefixing with '.' allowed local label.
After reading some docs i found this :
http://tigcc.ticalc.org/doc/gnuasm.html#SEC48L

Not really sure but it looks like using label$ instead of label: should do it :)

Post Reply