anrygraf Posted September 26, 2019 Share Posted September 26, 2019 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 Quote Link to comment Share on other sites More sharing options...
thorfdbg Posted September 26, 2019 Share Posted September 26, 2019 While I do not know the cc65 calling conventions for functions, one thing is for sure: you are *at least* missing an RTS at the end of your assembler function. Quote Link to comment Share on other sites More sharing options...
baktra Posted September 26, 2019 Share Posted September 26, 2019 (edited) 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 September 26, 2019 by baktra Clarified clearing the stack and returning Quote Link to comment Share on other sites More sharing options...
anrygraf Posted September 26, 2019 Author Share Posted September 26, 2019 (edited) 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 September 26, 2019 by anrygraf Quote Link to comment Share on other sites More sharing options...
baktra Posted September 26, 2019 Share Posted September 26, 2019 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 Quote Link to comment Share on other sites More sharing options...
baktra Posted September 26, 2019 Share Posted September 26, 2019 And how to debug? Use the Altirra emulator and its debugger facilities. Quote Link to comment Share on other sites More sharing options...
anrygraf Posted September 27, 2019 Author Share Posted September 27, 2019 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 Quote Link to comment Share on other sites More sharing options...
baktra Posted September 27, 2019 Share Posted September 27, 2019 (edited) 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 September 27, 2019 by baktra Attached project 1 Quote Link to comment Share on other sites More sharing options...
anrygraf Posted September 27, 2019 Author Share Posted September 27, 2019 (edited) 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 September 27, 2019 by anrygraf Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted September 27, 2019 Share Posted September 27, 2019 the "lda 10" is getting the value at a zeropage address? "lda #10" would give you a grey but "lda #$10" would give a very dark brown (PAL) Quote Link to comment Share on other sites More sharing options...
anrygraf Posted September 27, 2019 Author Share Posted September 27, 2019 32 minutes ago, Wrathchild said: the "lda 10" is getting the value at a zeropage address? Maybe I misunderstood the question, but "lda 10" - this instruction do load value 10 into accumulator. Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted September 27, 2019 Share Posted September 27, 2019 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. 4 Quote Link to comment Share on other sites More sharing options...
anrygraf Posted September 27, 2019 Author Share Posted September 27, 2019 Thanks a lot Wrathchild! It really helped me. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.