Question about ASM library in SDCC

By opcode

Expert (110)

opcode's picture

15-05-2021, 02:02

Hi there!

I am pretty good with assembly language, but have very little experience with C. Would someone please help me understand the principles behind an ASM library for C? To be honest this isn't MSX related, but I was tasked with creating a game library for a similar platform using Z80. So I would like to understand how my ASM routines should interface with SDCC for example.I saw some examples online, but I found the interface kind of inefficient, using the stack.

Any help would be greatly appreciated.

Login or register to post comments

By Bengalack

Paladin (802)

Bengalack's picture

15-05-2021, 08:28

I'm not 100% sure what you are asking, but I can say what I do.

I use SDCC quite a bit, and interface with asm all the time. I also use inline asm in C. Have a look here:
https://gist.github.com/Konamiman/af5645b9998c802753023cf1be...

I also use __naked when I can (this can only be used if the C-function, in fact, is all assembly), and __z88dk_fastcall as often as I can.

__naked skips the so-called prologue and epilogue (if I understand it correctly, all the pushing and popping of registers before and after a call).

__z88dk_fastcall is limited to ONE parameter only, and up to 32 bits. Passing parameters in HL or DEHL.

There is another keyword that is related here callee_saves, another one which gives the responsibility of the prologue and epilogue over to the callee, but I can't get it to work. I have a question at the SDCC-forums about it, but no answer yet: https://sourceforge.net/p/sdcc/discussion/1864/thread/2bb727...

Worth mentioning is that SDCC is working on getting more parameter passing over to registers. Head over here and vote it up: https://sourceforge.net/p/sdcc/feature-requests/253/

Note also that you can use the optimize flag when compiling to get faster code. This used to gain at least 10% performance (I used: "--opt-code-speed --max-allocs-per-node 2000000"), but with the latest version 4.1, many of these optimizations are coming out of the normal compile, and there is not too much to be gained.

By Bengalack

Paladin (802)

Bengalack's picture

15-05-2021, 08:40

Well, apart from all that, I mostly put assembler code in plain .s or .asm-files, and assemble them into .rel files using SDCC. Any function in the asm-files is used in the c-files using the extern-keyword, like:

extern void enterTitleScreen();

in the .s file this function must be called:

_enterTitleScreen::

The two colons tells the assembler that the symbol is public.

And at the end, you can just use sdcc to link all .rel-files together. Or .rel-file(s) + c-file in one go.

You can have a look at how things are done in the Fusion-C package, or even in a more pedagogic way, in DamnedAngel's packs: https://www.msx.org/forum/msx-talk/development/msx-template-...

And... well. there is more. The first .rel file, must be the crt0-file. It places the org, and the layout of "areas" (code, data, initializer), and must be handed over to the linked first.

By opcode

Expert (110)

opcode's picture

21-05-2021, 12:39

Thank you so much for all the info. Very useful and I really appreciate it. Now working on the new C library.

Some proof of concept done using the new hardware. We should have an additional more capable tile plane soon, for now using TMS9928 tile plane.

https://youtu.be/U09KFkzu6Fo

By jepmsx

Champion (281)

jepmsx's picture

10-12-2021, 21:32

Hi!

I'm trying to mix assembly files and C files using sdcc as it is suggested in this thread.

I've created an assembly file does do nothing called tonteria.s:

  .area _CODE

_functont::
  ld a,#5
  inc a
  ld l,a
  dec a
  xor a
  ret

and call it in another useless C program called tonteria.c:

extern void functont();

void main(){
  functont();
  int i =0;
  for(int k=0; k<10;k++){
    i=i+2;
  }
}

I've compiled the .s file using sdasz80 -o tonteria.s to get tonteria.rel. Then I've compiled it usign sdcc --code-loc 0x106 --data-loc 0x0 tonteria.rel tonteria.c and the linker complains that _functont is not defined.

What am I doing wrong?

Any help is very welcome

By the way, opcode, how is the game development going?

By aoineko

Paragon (1137)

aoineko's picture

10-12-2021, 23:24

I take this opportunity to answer the first question of the topic.
There are 3 main calling convention with SDCC depending on version and directive used on your function.

Here is a table that summarizes the registers used for the return value and the function parameters:

__sdcccall(0) => The default calling convention used on SDCC until version 4.1.11. All parameters are passed through the stack.
__sdcccall(1) => The new calling convention used by SDCC from version 4.1.12 (and future 4.2). First parameters are passed through registers and the rest through the stack.
__z88dk_fastcall => A specific calling convention (from z88dk compiler?) that allow to pass 1 parameter by register.

For your specific problem, I'm not sure of the problem.
Personally, I compile all my objects (c and assembler) independently, then I link all the .rel.
I don't know if you can mix compiled objects (.rel) and source files (.c). :-/

Here is the command line I use:

// Compile
SDASZ80 -o -l -s crt0_rom32.asm
SDCC -c -mz80 template.c
// Link
SDCC -mz80 --no-std-crt0 --code-loc 0x4010 --data-loc 0xC000 crt0_rom32.rel template.rel

By geijoenr

Champion (391)

geijoenr's picture

10-12-2021, 23:41

You are missing exporting the symbol in the .S file:

.globl _functont

you can mix .s files with .c files, as long as you export the symbols to be used outside each compilation unit.

By aoineko

Paragon (1137)

aoineko's picture

11-12-2021, 01:43

jepmsx wrote:

sdcc --code-loc 0x106 --data-loc 0x0 tonteria.rel tonteria.c

Hum... in fact I remember a problem when different objects have the same name (event if they have different source extension). Rename one of the file and I'm pretty sure your problem will disappear. Smile

By Bengalack

Paladin (802)

Bengalack's picture

11-12-2021, 08:08

aoineko wrote:
jepmsx wrote:

sdcc --code-loc 0x106 --data-loc 0x0 tonteria.rel tonteria.c

Hum... in fact I remember a problem when different objects have the same name (event if they have different source extension). Rename one of the file and I'm pretty sure your problem will disappear. Smile

Thanks!

I was puzzled by @jepmsx's problem because it seemed like everything was done right (you need to use your own "crt0" though). I tested things here too, and it didn't work. Until this came up. The filenames were the culprit Smile I have not been hit by this myself, but that is purely by chance Smile

Wrt. to .globl my understanding is that this is telling the assembler that these symbols are external symbols to "this file" (you can use the switch "-g" to ignore declaring them, and treat anything unknown as externals, as an alternative). The double :: exports the symbol.

By jepmsx

Champion (281)

jepmsx's picture

11-12-2021, 11:34

Thank guys for your information, I've learned a lot Cool . As Bengalack says the problem was the filename. I've changed them and it has compiled well Smile . I've also compiled with the .glob directive and without anb both have worked.