[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cc65 / ca65: how to interface C and assembly?



>>>>> "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/