Inline assembler with z88dk and sdcc

Amstrad CPC and NC systems
Post Reply
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Inline assembler with z88dk and sdcc

Post by andromeda92 »

Hi,
is it possible to have an example for z88dk and sdcc
regarding assembler in C code?
I tried several codes, but it never worked.

Code: Select all

#asm

#endasm

__asm

__endasm

"__asm" / "__endasm;"

_asm(

);

__asm__(" ... "); 
an idea ?
Thanks for your help.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

also I wanted to know for the affection of number, what should be put for z88dk and sdcc?

Code: Select all

ld a, 2 or

ld a, $2 or

ld a,#2 or

call 0xbb5a or

call #0xbb5a or

call $bb5a or

call #bb5a
in the example below it does not work, with z88dk

Code: Select all

int z88dk_putchar(char ch)
{
 __asm
 ld hl,2
 add hl,sp
 ld a,(hl)
 call 0xbb5a
 ld hl,1
 ret
 __endasm;

}
this is an example even if putchar already exists

when I say inline assembler I mean integrating assembler into C code


Thanks.
Timmy
Well known member
Posts: 400
Joined: Sat Mar 10, 2012 4:18 pm

Re: Inline assembler with z88dk and sdcc

Post by Timmy »

I think this thread probably showed some examples.

https://z88dk.org/forum/viewtopic.php?p=21669#p21669

There are probably some more posts too.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

I did like the example, both syntax compiles and generate .bin file but it displays nothing,
it should display A,

I tested both syntaxs:

Code: Select all

#asm
 ld a, 65
 call 0xBB5A
 #endasm

__asm
 ld a, 65
 call 0xBB5A
 __endasm;
The compilation line is

Code: Select all

"${config:z88_path}/bin/zcc.exe +cpc -create-app -lndos -mz80 -pragma-define:CRT_ORG_CODE=0x4000 -L${config:z88_path}/lib -I${config:z88_path}/ lib/target/cpc/def -I${config:z88_path}/include/arch/cpc -I${config:z88_path}/include ${workspaceFolder}/src/${workspaceFolderBasename}.c -o ${workspaceFolder} /bin/${workspaceFolderBasename}.bin"
the code is for amstrad CPC 6128, with z88dk.

I use WinCPC for emulator, on File/Load binaries.

call &4000
the screen is blue

i have put a while(1); at the end of program.
User avatar
dom
Well known member
Posts: 2148
Joined: Sun Jul 15, 2007 10:01 pm

Re: Inline assembler with z88dk and sdcc

Post by dom »

Please read: https://github.com/z88dk/z88dk/wiki/Pla ... e-firmware

You have to use the firmware interposer to call firmware routines
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

yes i read this document but EXTERN is for assembler or C ?

Code: Select all

EXTERN firmware
; Load registers
call firmware
defw call_address
how i use it ?

i copied file cpcfirm.del on my local source
#include "cpcfim.def"

i have error when i compile.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

[RESOLVED] Inline assembler with z88dk and sdcc

Post by andromeda92 »

ah yes it work

Code: Select all

void z88dk_printchar( char code )
{
    #asm        
        ld iy,$2
        add iy,sp ;Bypass the return address of the function 
        ld a,(iy)  ;code
        EXTERN firmware
        call firmware
        defw 0xbb5a       
    #endasm
}
thank you very much
Last edited by andromeda92 on Sun Apr 21, 2024 9:38 pm, edited 1 time in total.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

i have tested with clear screen, getch ... all work fine.
User avatar
dom
Well known member
Posts: 2148
Joined: Sun Jul 15, 2007 10:01 pm

Re: Inline assembler with z88dk and sdcc

Post by dom »

Probably something like this is what you're looking for.

Note that for sdcc, assembler is only understood within a function. So I've created a function to include cpcfirm.def. It's non-static because in certain cases, sdcc will optimise away non-referenced functions.

Code: Select all

void include_cpc_firmware_for_main(void) __naked
{
__asm
    EXTERN firmware
    INCLUDE "cpcfirm.def"
__endasm;
}

int main(void)
{
__asm
    ld a,'A'
    call firmware
    defw txt_output
__endasm;
    while(1) {}
    return 0;
}
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

thanks for this information.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

the function that include cpcfirm.def is only for sdcc ?
User avatar
dom
Well known member
Posts: 2148
Joined: Sun Jul 15, 2007 10:01 pm

Re: Inline assembler with z88dk and sdcc

Post by dom »

It'll work for both compilers, it's just necessary to it that way for sdcc.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

at first, I used the same syntax as for z88dk, but it works very well with z88dk

with sdcc it does not work for the three functions, it does not recognize the following keywords:

Code: Select all

EXTERN firmware and
defw  0xbb5a for example

Code: Select all

D:\data\dev\Z88DK\hello/bin\hello.asm:55: Error: <o> .org in REL area or directive / mnemonic error
D:\data\dev\Z88DK\hello/bin\hello.asm:57: Error: <q> missing or improper operators, terminators, or delimiters
D:\data\dev\Z88DK\hello/bin\hello.asm:66: Error: <o> .org in REL area or directive / mnemonic error
D:\data\dev\Z88DK\hello/bin\hello.asm:68: Error: <q> missing or improper operators, terminators, or delimiters
D:\data\dev\Z88DK\hello/bin\hello.asm:77: Error: <o> .org in REL area or directive / mnemonic error
D:\data\dev\Z88DK\hello/bin\hello.asm:79: Error: <q> missing or improper operators, terminators, or delimiters
listing assembler generated by compiler:

Code: Select all

_sdcc_printchar::
;D:\data\dev\Z88DK\hello/src/sdccapp.h:27: __endasm;
ld iy,#2
add iy,sp ;Bypass the return address of the function
ld a,(iy) ;code
EXTERNAL firmware
call firmware
defw 0xbb5a
;D:\data\dev\Z88DK\hello/src/sdccapp.h:28: }
ret
;D:\data\dev\Z88DK\hello/src/sdccapp.h:30: void sdcc_getch(void)
; ---------------------------------
; Function sdcc_getch
; ---------------------------------
_sdcc_getch::
;D:\data\dev\Z88DK\hello/src/sdccapp.h:36: __endasm;
EXTERNAL firmware
call firmware
defw 0xbb06
;D:\data\dev\Z88DK\hello/src/sdccapp.h:37: }
ret
;D:\data\dev\Z88DK\hello/src/sdccapp.h:39: void sdcc_clrscr(void)
; ---------------------------------
; Function sdcc_clrscr
; ---------------------------------
_sdcc_clrscr::
;D:\data\dev\Z88DK\hello/src/sdccapp.h:45: __endasm;
EXTERNAL firmware
call firmware
defw 0xbb6c
;D:\data\dev\Z88DK\hello/src/sdccapp.h:46: }
ret
User avatar
dom
Well known member
Posts: 2148
Joined: Sun Jul 15, 2007 10:01 pm

Re: Inline assembler with z88dk and sdcc

Post by dom »

If you're invoking sdcc directly then nothing in z88dk is going to help you! A vanilla sdcc uses the asxxxx assembler/linker and there's very limited compatibility with mnemonics.

However, if you add -compiler=sdcc to your zcc command line it will use our build of sdcc (binary is named z88dk-zsdcc) and that will work as you expect.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

you are right, adding -compiler=sdcc all work fine, now
indeed I used SDCC download separately,
I would use sdcc initially, it seems to work well, that said with z88dk I had fewer problems.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

I have a problem with the parameter pass and the stack, it doesn't work, I don't know if it's sp+2 or sp+4, do you have any idea?

Code: Select all

void cpc_plot (unsigned int x, unsigned int y)
{
 (void) x; // to avoid messages
 (void) y; // on unused parameters
 #asm
 ld iy,$4
 add iy,sp ;Bypass the return address of the function
 ld de,iy
 ld hl,(iy+2)
 call firmware
 defw gra_plot_absolute
 #endasm;
}
User avatar
dom
Well known member
Posts: 2148
Joined: Sun Jul 15, 2007 10:01 pm

Re: Inline assembler with z88dk and sdcc

Post by dom »

As usual, there's a wiki page for that: https://github.com/z88dk/z88dk/wiki/CallingConventions

For the code you've got there and for sdcc, &y = sp+2, &x = sp +4

If you add -a to your command line you can check the generated code.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

it work now, in the documentation for standard (on z88dk), i think it's a same for sdcc,
the stack is pushed from right to left.

for this command gra_plot_relative

Code: Select all

DE = x
HL = Y

iy = (SP+2)
iy = SP+4 (SP+2 + 2) 
because iy is already SP+2 with

Code: Select all

ld iy,$2
add iy,sp 
the code below work

Code: Select all

void cpc_plot (unsigned int x , unsigned int y)
{
    (void) x;   // pour éviter les messages
    (void) y;   // sur les paramètres non utilisés
    #asm
        ld iy,$2
        add iy,sp ;Bypass the return address of the function 
        ld hl,(iy)
        ld de,(iy+2)                    
        call firmware
        defw gra_plot_relative
    #endasm;
}
thank you.
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

for inline assembly or integrated assembly in C, in the example functions that I posted above, which uses ix or iy, normally I should save them on the stack before and at the end of the routine?

Code: Select all

push ix or push iy
.....
pop ix or pop iy
andromeda92
Member
Posts: 22
Joined: Wed Apr 17, 2024 1:05 am

Re: Inline assembler with z88dk and sdcc

Post by andromeda92 »

ah no, because SDCC automatically adds IX register management at compilation time
Post Reply