[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: cc65 / ca65: how to interface C and assembly?
- Subject: Re: cc65 / ca65: how to interface C and assembly?
- From: MagerValp <MagerValp@cling.gu.se>
- Date: 06 Dec 2005 18:20:47 +0100
- Newsgroups: comp.sys.apple2, comp.sys.cbm, comp.sys.atari.8bit
- Organization: Educational Programme in Computational Linguistics, Göteborg University
- References: <4395b60d$0$9636$9b4e6d93@newsread2.arcor-online.net>
- Sender: cl3polof@panini.cling.gu.se
- User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.1
- Xref: g2news1.google.com comp.sys.apple2:7139 comp.sys.cbm:12746 comp.sys.atari.8bit:3612
>>>>> "LT" == Linards Ticmanis <ticmanis@gmx.de> writes:
LT> I'd like best to use inline assembly ("asm") statements inside a C
LT> frame function, but the code is not allowed to cross a page boundary,
Unfortunately, this rules out inline __asm__ statements.
LT> If I can't use inline assembly, I'd need to know how to interface
LT> assembly and C code.
Sure thing, it's simple enough. The software stack is implemented with
a zp pointer called sp. It starts at the top, and moves down as items
are pushed on the stack. You can .importzp sp and access it directly,
but it's easier to use the built in library calls for manipulating the
stack. When your code is called, the arguments are pushed onto the
stack left to right. If you declare your function __fastcall__ the
last (rightmost) argument will be in A/X instead of on the stack,
which saves a few cycles. Your code is responsible for pulling all the
arguments off the stack, so if you have e.g. 4 bytes of arguments, sp
should be increased with 4 before your code exits (2 if you use
__fastcall__). The return value should be in A (lo) and X (hi). X must
be set even if you just return a single byte, as cc65 doesn't clear X
for you if the value is cast e.g. from a char to an int.
Some of the available library routines are:
popa pull one byte off stack, increase sp by one
popax pull two bytes off stack, increase sp by two
pusha dec sp byte one, push one byte onto the stack
pushax dec sp by two, push two bytes onto stack
incsp1 increase sp by one
incsp2 increase sp by two (and so on)
Here's a silly example that copies 1-128 bytes from src to dst, and
returns the length:
-- main.c --
#include "copyshort.h"
void main(void) {
copyshort(10, 0x1000, 0x2000);
}
-- copyshort.h --
/* copy 128 bytes or less from, returns bytes copied */
extern unsigned char __fastcall__ copyshort(unsigned char len, void *src, void *dst);
-- copyshort.s --
.export _copyshort ; prepend labels with _ so C can see them
.import popa, popax
.importzp ptr1, ptr2
src = ptr1 ; borrow runtime zp pointers
dst = ptr2 ; tmp1 and tmp2 are also available
.code
_copyshort:
sta dst ; __fastcall__ so last arg is
stx dst + 1 ; in A/X
jsr popax ; pull src off stack
sta src
stx src + 1
jsr popa ; pull len off stack
pha ; save len for return value
tay
dey
: lda (src),y
sta (dst),y
dey
bpl :-
ldx #0 ; return len in A/X
pla
rts
LT> If there are any web forums or mailing lists where this question is
LT> more likely to get useful answers, I'd be also grateful for a link.
Check out the cc65 mailing list:
http://www.cc65.org/#List
--
___ . . . . . + . . o
_|___|_ + . + . + . Per Olofsson, arkadspelare
o-o . . . o + MagerValp@cling.gu.se
- + + . http://www.cling.gu.se/~cl3polof/