| |
Slammer
Registered: Feb 2004 Posts: 416 |
Kick Assembler Thread 2
The previous thread took a little long to load, so this is a new fresh one.. |
|
... 590 posts hidden. Click here to view all posts.... |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Then an another little puzzle, which could ease up the programming a bit for sure... (atleast if you branch a lot =)
When a relative branch exceeds its short branch limits in multiple places in the code, it could get annoying to replace it with long jumps, but optimize back a bit later if not needed... So i wanted to automate some long branch generation a bit, instead of several compile time complaints. BUT! Is this possible to do properly in kickassembler? As i know kick can do multiple passes depending on your code, until all variables are known and all code generated properly? :)
What do you think? How this should be done? My idea is this (and it halfway works already!)
.const BEQ=$f0 .const BNE=BEQ^$20
.const BMI=$30 .const BPL=BMI^$20
.const BCC=$90 .const BCS=BCC^$20
.pseudocommand far OPCODE;OPERAND {
.var PC = *
.var branch = OPERAND.getValue()-PC
//.if (branch ?? InvalidNumber) { .print "label not found yet" } //...should this work?
.if ( branch < -126 || branch > 129 ) {
.byte OPCODE.getValue()^$20, 3 // [BEQ] *+5, jmp long_branch
jmp OPERAND
.print"FAR BRANCH at location $"+toHexString(PC)
} else {
.byte OPCODE.getValue(), branch-2 // [BNE] short_branch
// For the above .byte code, is there possible to feed OPCODE for pseudocommand like those argument types for operand?
}
}
.pc=$2000 // some testing...
before:
.fill 127,[NOP]
:far BNE; before // this branch works
:far BCC; after // this branch gives "Error: the condition must be able to evaluate in first parse)"
.fill 128,[NOP]
after:
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Quote:.for (var i=0; i<=10; i=i+0.1) { .if (i>5) .eval i=5 .print "i="+i }
The error in the above example is happening due to an endless loop (but I guess you knew thats why you made the example). I dont think i have alot to go on but if you get the error againg let me know. (NB. all numbers in KickAss is pratically doubles, so I dont think it got anything todo with int vs float comparison)
Regarding the branch thing. I had the same thouht once but concluded that this kind of functionality have to be implemented in a 'trial and error' kind of way. When deciding if the branch is a short or a long one you should know the target address of the branch. But the target address of the branch could depend on wether its a short or a long branch, so this is a problem. Further more several branches could be dependand on each others decitions (short vs far) so this makes it more complicated. This is a thing for the assembler to support by first assuming short jumps and then reassemble with long jumps until all branches fits. I have a note on the which list for implementing this as jne, jeq, jmi, jpl, etc but this is a biggie so it wont be this year. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Question about functions/macros. There's clear division which does what in manual. How about piece of code that is mix of assembler and script conditions/variables - should I define the one below as macro or function?
.if(usefreqtable1)
{
.if(usefreqlo1)
{
ldx #$00
checkch1freq:
lda ch1freq, x
cmp #$fe
bne updatech1freq
ldx #$00
stx checkch1freq - 1
jmp checkch1freq
updatech1freq:
sta $d401
.if([usefreqhisweeptable1] || [constfreqhisweep1 != $00])
{
sta dofreqhisweep1 + 1
}
inx
lda ch1freq, x
sta $d400
.if([usefreqlosweeptable1] || [constfreqlosweep1 != $00])
{
sta dofreqlosweep1 + 1
}
inx
stx checkch1freq - 1
}
else
{
ldx #$00
checkch1freq:
lda ch1freq, x
cmp #$fe
bne updatech1freq
ldx #$00
stx checkch1freq - 1
jmp checkch1freq
updatech1freq:
sta $d401
.if([usefreqhisweeptable1] || [constfreqhisweep1 != $00])
{
sta dofreqhisweep1 + 1
}
inc checkch1freq - 1
.if([usefreqlosweeptable1] || [constfreqlosweep1 != $00])
{
lda #$00
sta dofreqlosweep1 + 1
}
}
}
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
It would have to be a macro (or pseudo command). Commands that produces bytes to the resulting .prg file (like mnemonics and .byte/.word etc) can't be in functions.
Edit: Otherwise you could make some really tricky stuff like:lda #myByteProducingFunc(27) |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
I've tried to define that portion of code both as macro and function. Macro resulted in error due to non-assembly instructions. Function compiled without error but most probably as regular assembly that's not really a subroutine. Ok, I see that it has to be totally reorganized ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
If you are reporting error please post complete examples. When you post cutout pieces of code I have no chance of verifying if its an error or not.
I dont think I understand what you are writing. Are you sure its not when you put it in a function you get an error for using asm directives? ( = directives that produce bytes to the output) |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Sorry about that :) Macro seems to work fine - it was just enclosed within .if directive that I didn't catch somehow. No error report whatsoever and thank you for the tip ;) |
| |
Hoogo
Registered: Jun 2002 Posts: 102 |
I guess there are situations where automatic long branches are difficult:
---> Dest 1
| ...
| -<Branch 2
| | ...
--+<Branch 1
| ...
-->Dest 2 Branch2 cannot be decided until Branch 1 was decided, and the other way around the same.
But such a situation can already be created with an .if (futureLabelFormual)FillSomeBytesFormula. How do you treat that? Forbid .if with unknown labels? Or some check if passes get out of sync? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You guessed it , using if's on yet unknown values gives an error since the memlocation of labels have to be resolved in first pass. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I saw I asked this thing like 4 years ago and surely found some work-around back then but that is several HD crashes ago and perhaps there are updates I didn't catch.
Strings:
I am making a string for a cartridge header but it contains some RVRS ON characters and stuff. The question is how do I avoid doing this hack:
.const CartridgeName = "C64GS C" // Maximum 32 bytes.
.text CartridgeName
.byte $61,$72,$74,$72,$69,$64,$67,$65
Basically what I would like to do is to append the constant with the bytes as added data to the string. This again to allow me to fill in the surplus available characters without having to cheat:
.fill 32-CartridgeName.size()-8,0
So what I would like to do is:
.const CartridgeName = "C64GS C"+hexBytes($61,$72,$74,$72,$69,$64,$67,$65) |
Previous - 1 | ... | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ... | 61 - Next |