Offsets

JMP $FCE2
ajordison
Developer
Developer
Posts: 59
Joined: Wed Apr 16, 2014 1:28 pm
Location: Hartlepool, UK
Contact:

Offsets

Post by ajordison »

I've been asked to add an 'offset' directive to CBM prg Studio and as an example he copied and pasted the example from the Turbo Macro Pro site (.offs) :

http://turbo.style64.org/docs/turbo-mac ... mpx-syntax

I've read the documentation a few times and basically I'm just not getting it! Can someone explain how this works, or even if it's useful?


Try out CBM prg Studio for all your Commodore development needs!
Stay a while...stay for erm quite a while!
Prime

Re: Offsets

Post by Prime »

An X,Y IndexOffset macro in assembly Arthur?Is that what you mean?
Oh directive
Wanax
Member
Member
Posts: 17
Joined: Sat Apr 12, 2014 6:15 pm
Location: italy
Contact:

Re: Offsets

Post by Wanax »

Acme use !pseudopc for offset assembly, is useful for create crt type EFlash and other version....
satpro

Re: Offsets

Post by satpro »

ajordison wrote:I've been asked to add an 'offset' directive to CBM prg Studio and as an example he copied and pasted the example from the Turbo Macro Pro site (.offs) :

I've read the documentation a few times and basically I'm just not getting it! Can someone explain how this works, or even if it's useful?
I put the section here:

Pseudo-ops: Code Offsets

The .offs pseudo op is used to alter the memory address to where code is being assembled. This sounds identical to the function of the program counter (*) but there is a distinction: * sets the "effective address" for assembled code, meaning, object code is generated assuming that it is located at the address in the program counter. But .offs changes the "actual address" to where object code is assembled. If you do not use calls to .offs in your code, then the actual address and effective address will remain identical. Used together, you can assemble code so that it will execute properly in a different part of memory than where the code itself is located in the assembled output.

.offs - change the location that code is assembled to; code will be assembled forward
in memory the the value of the expression following .offs

Code: Select all

 -=> Example

     (this code)   ->  (assembles as)
       * = $2000
start  bit base0       bit $2009
       bit base        bit $8000
       jmp *           jmp $2006
base0  * = $8000
base   .offs base0-*
       lda #>start     lda #$20
       jmp *           jmp $8002
This code is assembled from $2000 to $200d; by using an expression for the .offs we can generate code in a contiguous memory span, even though part of the code has been assembled to execute at a different memory address (in this case, $8000). In this example the .offs is effectively offsetting the assembled code backwards in memory. Naturally this can be extremely useful for coding routines that need to execute in zero page, or for coding routines to run in drive memory.

This could be useful in a program loaded to BASIC $0801, with an embedded 8K module intended to be executed under $A000. From your end it is a temporary program counter for the block contained between the .offs directives. So everything within that block is assembled as if it executes at $A000, but the rest of the program it is embedded in runs with the normal program counter @ $0801.

It was mentioned above, but drive code is the ideal candidate for an .offs directive. The other thing is that some assemblers (and I don't know why) use the offset operand as an offset from the current program counter, which seems lazy, cumbersome, and prone to error to me. The traditional method is to allow a programmer to embed a block of code, then stipulate the address it will run from after it is moved to that address.
ajordison
Developer
Developer
Posts: 59
Joined: Wed Apr 16, 2014 1:28 pm
Location: Hartlepool, UK
Contact:

Re: Offsets

Post by ajordison »

Thanks guys, I think I've got the hang of now. I looked at the pseudopc directive that kickassembler uses and that had a good example, which cleared up the Turbo Macro example:

In case you want your code placed at position $1000 in the memory but want it assembled like it was placed at $2000, you can use the .pseudopc directive:

Code: Select all

.pc = $1000 "Program to be relocated at $2000"
.pseudopc $2000 {
loop:   inc $d020
        jmp loop  // Will produce jmp $2000 instead of jmp $1000
}
This leads me neatly to another question. Kickassembler uses the { } braces to define the scope of the directive but prg studio only has scope in the current label. This probably wouldn't be good enough, so how do other assemblers do it? I suppose an easy way is to just reset the directive by cancelling the offset but this seems a bit crude.
Try out CBM prg Studio for all your Commodore development needs!
Stay a while...stay for erm quite a while!
satpro

Re: Offsets

Post by satpro »

ajordison wrote:This leads me neatly to another question. Kickassembler uses the { } braces to define the scope of the directive but prg studio only has scope in the current label. This probably wouldn't be good enough, so how do other assemblers do it? I suppose an easy way is to just reset the directive by cancelling the offset but this seems a bit crude.
Maybe I am mis-understanding the quoted text above, but wouldn't an offset block be defined as being the data located between the .offs directives, meaning a temporary context only good for that section of code, and then any number of sub-contexts (nested) within that primary, relocated context? As soon as the first directive hits, you switch to the temp context (a specified program counter and any other special [temporary] changes you might need), and then after the second directive hits, everything goes back to normal. In many ways, just another local section with private labels (and external to the $0801 code), relocated and run in the specified location. In a way the directive becomes a toggle switch for the program counter, allowing you to switch in and out to the temp PC as necessary.

I think Kickassembler's use of brackets is consistent with what the author is seemingly trying to accomplish: object-oriented assembly. These days there is a growing trend in assembly to code OO, and since many programmers have the background, the finished product can be coded easier (and faster) for them. Where the 1 mhz c64 is concerned, the trade-off with programming C-style is expense -- it's generally magnitudes slower by way of additional overhead.
dudz
Member
Member
Posts: 140
Joined: Tue Jun 17, 2014 5:40 am
Contact:

Re: Offsets

Post by dudz »

imho using scopes for pc offset isnt ideal, because its two different things... ca65 uses .org and .reloc directives for this (but then again ca65 is very different to most other c64 related assemblers)
satpro

Re: Offsets

Post by satpro »

dudz wrote:imho using scopes for pc offset isnt ideal, because its two different things... ca65 uses .org and .reloc directives for this (but then again ca65 is very different to most other c64 related assemblers)
Why is it not ideal? Please explain the two different things are you referring to. What makes ca65 different, other than its non user-friendly interface and completely non-standard syntax?
dudz
Member
Member
Posts: 140
Joined: Tue Jun 17, 2014 5:40 am
Contact:

Re: Offsets

Post by dudz »

Why is it not ideal? Please explain the two different things are you referring to.
scopes are commonly used for defining in what area you can refer to symbols and labels, not to define program placement.
What makes ca65 different
unlike most other (8bit) assemblers, which do program placement using the special "*" symbol, ca65 has a real linker which does all the relocation - much like most assemblers for "bigger" systems work (like GAS).
satpro

Re: Offsets

Post by satpro »

dudz wrote:unlike most other (8bit) assemblers, which do program placement using the special "*" symbol, ca65 has a real linker which does all the relocation - much like most assemblers for "bigger" systems work (like GAS).
That sounds like semantics. If by "real linker" you mean external, then ca65 qualifies, but that doesn't make it any better than an assembler such as 64Tass (or even CPS, lucky us to have it developed before our very eyes). I have yet to find a single thing 64Tass can't handle that ca65 can. Nothing. And I do a lot of weird stuff in both worlds -- x86 & 65x. The truth is, ca65 is great in terms of function and feature, but it's an absolute disaster on the user-friendly front -- the exact opposite of what a programming environment should be. Fix that one thing -- you have a winner.
scopes are commonly used for defining in what area you can refer to symbols and labels, not to define program placement.
I was simply trying to make a comparison in how you might visualize the concept. A locally scoped section is nothing more than a convenient way for the programmer to re-use labels -- that's it -- and I know you know that. Local scopes are concepts, not things. For that matter, so are structures and unions, as is everything else past the plain old mnemonic. The notion of private or public labels is something made up by the high level, object-oriented crowd anyway. So, as assembly programmers we make use of those concepts and are able to "create" local sections anywhere -- even within re-located code -- just as they do in the HLL world. We certainly wouldn't have to, and it's hardly a thing to debate.

What I was asking is how the opinions you shared can be used to help Arthur. We all have a favorite assembler; the topic here is how to go about getting an offset directive into CPS -- not the philosophical pros and cons.

When it comes to disrupting a thread I'm as guilty as you are dudz, so it stops now. All I'm asking is that you read what the guy writes before going off on your little sideshows. Vague, nebulous opinions are cheap. If you know how to get an offset directive into CBM prg Studio -- now is the time to present the plan.
Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 5 guests