Jump to content
IGNORED

Calling asm proc from C


anrygraf

Recommended Posts

Hi everyone!
I started programming A8 in the C (CC65).
My idea is doing main programming in C and call assembler subprograms.
It's work fine, but I don' t know how I can make a call the assembler procedure with arguments.

For test, I wrote small code for change border color.

I can't understand why it doesn't works, pls help me..

/* 
/ main.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern void foo(uint8_t c);

int main() {
	foo(10);
	while(1){}
    return 0;
 }

 

; 
; foo.s
;
.importzp sp, sreg, regsave
.export _foo

.segment	"CODE"

.proc _foo: near
; get arguments
ldy #$00
lda (sp),y
; set border color
sta 712
.endproc

 

For building

cl65 -t atari main.c foo.s -o app

 

Link to comment
Share on other sites

Write the same function in C and then observe the contents of the .s file.

The RTS instruction is missing for sure, as thorfdbg suggested.

 

void foo(uint8_t c) {
    POKE(712U,c);
}

 

; ---------------------------------------------------------------
; void __near__ foo (unsigned char)
; ---------------------------------------------------------------

.segment    "CODE"

.proc    _foo: near

.segment    "CODE"

    ldy     #$00
    ldx     #$00
    lda     (sp),y       ;Grab the last parameter from the parameter stack to A
    sta     $02C8        ;Use it
    jsr     incsp1       ;Clean parameter stack
    rts                  ;Return (using hardware stack)

.endproc

 

More information here: https://github.com/cc65/wiki/wiki/Parameter-passing-and-calling-conventions

Edited by baktra
Clarified clearing the stack and returning
Link to comment
Share on other sites

Thanks you guys!

This is my mistake, RST instruction really need.

I fixed my assembler code as baktra said.

But problem not solved, the FOO function not get right value from stack.

How can I do debugging the code at execution?

Edited by anrygraf
Link to comment
Share on other sites

I believe I see the reason.

 

There are two calling conventions. cdecl and fastcall. If you do not specify otherwise, CC65 uses fastcall. With fastcall, the last parameter is passed through register A and not through parameter stack.

In my example, I was using cdecl, but you are obviously using fastcall.

 

With fastcall, it looks like this. Since you are implementing the function in assembler, you can (but do not have to, of course) remove the red lines

; ---------------------------------------------------------------
; void __near__ __fastcall__ foo (unsigned char)
; ---------------------------------------------------------------

.segment    "CODE"

.proc    _foo: near

.segment    "CODE"

    jsr     pusha
    ldy     #$00
    ldx     #$00
    lda     (sp),y

    sta     $02C8
    jsr     incsp1
    rts

.endproc

 

Link to comment
Share on other sites

Thanks again baktra!

I tried call asm proc as you recommended as fastcall.

But anyway I got wrong value in asm.

I don't not what happened, why this code don't working correctly.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void fastcall foo(uint8_t c);

int main() {
	foo(10);
	while(1){}
  
	return 0;
 }
.importzp sp
.import incsp1
.export _foo

.segment    "CODE"
.proc    _foo: near
.segment    "CODE"
    sta     $02C8
    rts
.endproc

 

Link to comment
Share on other sites

28 minutes ago, anrygraf said:

Thanks again baktra!

I tried call asm proc as you recommended as fastcall.

But anyway I got wrong value in asm.

I don't not what happened, why this code don't working correctly.


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void fastcall foo(uint8_t c);

int main() {
	foo(10);
	while(1){}
  
	return 0;
 }

.importzp sp
.import incsp1
.export _foo

.segment    "CODE"
.proc    _foo: near
.segment    "CODE"
    sta     $02C8
    rts
.endproc

 

That is very strange.

I've created a project, copy-pasted your sources, compiled the same way, and when running it, the border color is gray, as expected.

 

What version of CC65 are you using?

 

cc65 --version

responds 

cc65 V2.17 - Git d52d986

 

test.zip

Edited by baktra
Attached project
  • Like 1
Link to comment
Share on other sites

cc65 V2.16 - Ubuntu

 

Yes, I get also gray color, but shouldn't the color be brown?

For experiment, in this case I got brown border color.

I think this problem in the format number representation hex/dec.

.importzp sp
.import incsp1
.export _foo

.segment    "CODE"
.proc    _foo: near

.segment    "CODE"
    lda 10
    sta $02C8
    rts
.endproc

 

Edited by anrygraf
Link to comment
Share on other sites

32 minutes ago, anrygraf said:

"lda 10" - this instruction do load value 10 into accumulator

No, the hash (#) is to indicate the value is an 'immediate' value.

The dollar ($) is to indicate that the following value is 'hexadecimal'

 

so your "sta $02C8" would be equivalent to "sta 712", this refers to an 'absolute' address.

 

therefore "lda 10" means "load the accumulator from address 10" and a "lda $10" would be from address 16.

 

hence "lda #10" is "load the accumulator with the value 10" and "lda #$10" would be the value 16.

 

Hope that helps.

  • Like 4
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...