This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

ld65 overflow - alignment gaps?

ld65 overflow - alignment gaps?
by on (#157217)
I'm getting slightly over the allocated space:
ld65: Warning: nes.cfg(15): Memory area overflow in `PRG', segment `DATA' (14 bytes)

However, the summed output from od65 says there's several kilobytes free. To me that says there's unoptimal packing, most likely due to alignment requirements leaving empty gaps. Am I right?

If so, is there any tool to show the alignment gaps? On x86 the closest would be pahole, but that's for structs, not linker placement.
Re: ld65 overflow - alignment gaps?
by on (#157220)
DATA refers to initialized writable data that's copied into RAM at program start, as opposed to RODATA that's read-only data. Usually on the NES, there's little or no DATA, and any initialized writable data is copied into RAM at the start of a particular level.

You can have ld65 generate a map file, which should show how things are being packed.
Re: ld65 overflow - alignment gaps?
by on (#157228)
Ah, thanks, that's useful.

I have no DATA, it just happened to be the last thing the linker processed, thus in the error.
Re: ld65 overflow - alignment gaps?
by on (#157414)
tepples wrote:
You can have ld65 generate a map file, which should show how things are being packed.

ld65 doesn't actually generate the map file unless the link is successful, I believe? (Edit: it does in some cases, not in others, see below.) So, in the case of an overflow you can't actually use it to help, unfortunately. (Or if I'm doing it wrong, please let me know, because I'd love to have a map of an overflow.)

There's only a few things that can create alignment gaps, I think:

1. Explicit align or start address in linker CFG files.
2. .org directive in source file.
3. .align directive in source file.

I'd recommend only using method 1. Create segments with specific alignment or start addresses in your CFG file and just use those segments in the source files.

Method 2 is recommended against by the ca65 documentation, mostly because it conflicts with the job of the linker, which has the specific task of deciding where to put the assembled code. Using .org constrains it, and make things harder to pack. If you have any .org directives, I'd recommend finding a way to remove them if possible, and switch to using method 1 where you need alignment or other specific layout.

Method 3 is a little bit problematic, because it is relative to the position in the output file, I believe, not the PC, which means if you have, for example, a 16 byte iNES header in your output, your align is going to be shifted by 16 bytes from what you probably want.
(Edit: this appears to be untrue. See below.)
Re: ld65 overflow - alignment gaps?
by on (#157415)
ld65 should produce the map file even if there's a segment overflow (as far as I remember, it generates info up to (and including) the segment list.)

About .org in ca65, it's a little bit different than in many other assemblers. It doesn't actually place code in a specific location, it only tells the assembler to assemble the code as if the code was at the specified place. It will still go into the current segment. So the linker doesn't really care about it. Another "gotcha" (which is related to the above) is that it doesn't add any padding (padding can be manually added with .res).

Code:
.org $4444
jmp * ; Assembles to jmp $4444, regardless of the current segment address
.org $5555
jmp * ; Assembles to jmp $5555, but in output file it will come flush after the jmp $4444
Re: ld65 overflow - alignment gaps?
by on (#157417)
rainwarrior wrote:
Method 3 is a little bit problematic, because it is relative to the position in the output file, I believe, not the PC, which means if you have, for example, a 16 byte iNES header in your output, your align is going to be shifted by 16 bytes from what you probably want.

In what way? Can you provide a test case (.s and config) for this behavior? As far as I've been able to tell, it aligns relative to the memory area, meaning .align 256 in a segment destined for PRG ROM will put something at an offset of $xx00 in PRG ROM space or $xx10 in the iNES file.

.org as described by thefox sounds more like it'd be useful for code that gets copied into RAM. But what I've used for that is another .segment.
Re: ld65 overflow - alignment gaps?
by on (#157423)
For my original guess, it wasn't about the cross-section packing (and the map file was useless for what I had in mind anyway, which is per-variable packing, with u8 and u16 next to each other causing a gap - the map file only listed sections). It was the printf machinery taking 1.7kb.
Re: ld65 overflow - alignment gaps?
by on (#157433)
tepples wrote:
Can you provide a test case (.s and config) for this behavior? As far as I've been able to tell, it aligns relative to the memory area, meaning .align 256 in a segment destined for PRG ROM will put something at an offset of $xx00 in PRG ROM space or $xx10 in the iNES file.

It looks like I am wrong about it. What I said was based on what I remember trying to use it a few years ago (and because it didn't appear to be MEMORY aligned, it seemed to be useless and I hadn't tried it since). Either it has been corrected since, or I was mistaken then.

thefox wrote:
ld65 should produce the map file even if there's a segment overflow (as far as I remember, it generates info up to (and including) the segment list.)

After looking at this a bit more, I determined that for just a segment overflow, it does indeed produce the map. If it is a segment overflow, followed by a "start address too low" error (e.g. if you have a vectors segment starting at $FFFA) the map is not generated, which is vexing.