Weird Assembler Issue
-
kellymcdonald78
- Posts: 3
- Joined: 04 Jan 2026
Weird Assembler Issue
Had my "Hello World", code running successfully the other day. Added some additional functionality to initialize my ACIA and output data to the serial port. However now my assembled hex dump doesn't seem to make sense. I normally start things off by setting the stack pointer LDX #FF and STX opcode, but for some reason my rom file keeps starting with $9C (which is STZ). I comment out my stack code and re-assemble (including deleting my old .bin and doing a make clean) and no change.
I'm using dhirsch1138's c65 container running under Docker Desktop
I'm using dhirsch1138's c65 container running under Docker Desktop
Re: Weird Assembler Issue
Can you show a list file?
(And did you mean 'TXS'?)
Neil
(And did you mean 'TXS'?)
Neil
-
kellymcdonald78
- Posts: 3
- Joined: 04 Jan 2026
Re: Weird Assembler Issue
;PURPOSE - This is the code which will written to ROM at $0000 (but will be referenced as $8000)
;
;
;The first difference we'll see is the inclusion of other source files (note they do not have .s extensions, we do not want
;them assembled as their own objects).
; ca65 documentation: https://cc65.github.io/doc/ca65.html#ss11.66
;
;Include the via import file (defining the imports there and keeping this source clean)
.include "via.s_imports"
;Include the acia (serial) import file
.include "acia.s_imports"
;Include the reset and interrupt vector definitions
.include "reset.s_interrupts"
.include "lcd.s_imports"
.code
setmode:
ldx #$FF
txs
clc ; Clear carry to set addition mode
xce ; Switch to native mode
sei ; Disable interrupts
cld ; Clear decimal mode
; Now in native mode with interrupts disabled and stack set
sep #%00110000 ; Set to 8-bit accumulator and index registers
jsr via_init ;Initialize VIA
jsr acia_init ;Initialize ACIA (serial)
jsr lcd_init ;Initialize LCD
jsr print_hello ;Print "Hello, World!" to the LCD
main:
nop ; dummy instruction
nop ; dummy instruction
nop ; dummy instruction
lda #'H'
jsr acia_putchar
jmp main ; Infinite loop to keep the program running;
00000000 9c 91 7f a9 1a 8d 93 7f a9 19 8d 92 7f 60 aa 8e |.............`..|
00000010 90 7f 84 ff 88 d0 fd 60 a9 08 2c 91 7f f0 fb ad |.......`..,.....|
00000020 90 7f 60 18 fb 78 d8 e2 30 20 3b 81 20 00 80 20 |..`..x..0 ;. .. |
00000030 82 80 20 40 80 ea ea ea a9 48 20 0e 80 4c 35 80 |.. @.....H ..L5.|
00000040 a9 48 20 c1 80 a9 65 20 c1 80 a9 6c 20 c1 80 a9 |.H ...e ...l ...|
00000050 6c 20 c1 80 a9 6f 20 c1 80 a9 2c 20 c1 80 a9 20 |l ...o ..., ... |
00000060 20 c1 80 a9 57 20 c1 80 a9 6f 20 c1 80 a9 72 20 | ...W ...o ...r |
00000070 c1 80 a9 6c 20 c1 80 a9 64 20 c1 80 a9 21 20 c1 |...l ...d ...! .|
00000080 80 60 a9 01 20 97 80 a9 38 20 97 80 a9 0f 20 97 |.`.. ...8 .... .|
00000090 80 a9 06 20 97 80 60 48 20 12 81 fa ad 81 7f 29 |... ..`H ......)|
000000a0 f8 8d 81 7f 8e 80 7f a2 ff 8e 82 7f 09 01 8d 81 |................|
000000b0 7f 29 f8 8d 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f |.)..............|
000000c0 60 48 20 12 81 fa ad 81 7f 29 fc 09 04 8d 81 7f |`H ......)......|
000000d0 8e 80 7f a2 ff 8e 82 7f 09 05 8d 81 7f 29 f8 8d |.............)..|
000000e0 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f 60 ad 81 7f |............`...|
000000f0 a9 00 8d 82 7f 29 fa 09 02 8d 81 7f 09 03 8d 81 |.....)..........|
00000100 7f ae 81 7f 29 f8 8d 81 7f 8a 29 7f a2 ff 8e 82 |....).....).....|
00000110 7f 60 ae 81 7f 8a a9 00 8d 82 7f 29 fa 09 02 8d |.`.........)....|
00000120 81 7f 09 03 8d 81 7f aa ad 80 7f 89 80 d0 e6 8a |................|
00000130 29 f8 8d 81 7f a9 ff 8d 82 7f 60 a9 00 8d 81 7f |).........`.....|
00000140 a9 00 8d 80 7f a9 ff 8d 83 7f a9 ff 8d 82 7f a9 |................|
00000150 cc 8d 8c 7f 60 00 00 00 00 00 00 00 00 00 00 00 |....`...........|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
;
;
;The first difference we'll see is the inclusion of other source files (note they do not have .s extensions, we do not want
;them assembled as their own objects).
; ca65 documentation: https://cc65.github.io/doc/ca65.html#ss11.66
;
;Include the via import file (defining the imports there and keeping this source clean)
.include "via.s_imports"
;Include the acia (serial) import file
.include "acia.s_imports"
;Include the reset and interrupt vector definitions
.include "reset.s_interrupts"
.include "lcd.s_imports"
.code
setmode:
ldx #$FF
txs
clc ; Clear carry to set addition mode
xce ; Switch to native mode
sei ; Disable interrupts
cld ; Clear decimal mode
; Now in native mode with interrupts disabled and stack set
sep #%00110000 ; Set to 8-bit accumulator and index registers
jsr via_init ;Initialize VIA
jsr acia_init ;Initialize ACIA (serial)
jsr lcd_init ;Initialize LCD
jsr print_hello ;Print "Hello, World!" to the LCD
main:
nop ; dummy instruction
nop ; dummy instruction
nop ; dummy instruction
lda #'H'
jsr acia_putchar
jmp main ; Infinite loop to keep the program running;
00000000 9c 91 7f a9 1a 8d 93 7f a9 19 8d 92 7f 60 aa 8e |.............`..|
00000010 90 7f 84 ff 88 d0 fd 60 a9 08 2c 91 7f f0 fb ad |.......`..,.....|
00000020 90 7f 60 18 fb 78 d8 e2 30 20 3b 81 20 00 80 20 |..`..x..0 ;. .. |
00000030 82 80 20 40 80 ea ea ea a9 48 20 0e 80 4c 35 80 |.. @.....H ..L5.|
00000040 a9 48 20 c1 80 a9 65 20 c1 80 a9 6c 20 c1 80 a9 |.H ...e ...l ...|
00000050 6c 20 c1 80 a9 6f 20 c1 80 a9 2c 20 c1 80 a9 20 |l ...o ..., ... |
00000060 20 c1 80 a9 57 20 c1 80 a9 6f 20 c1 80 a9 72 20 | ...W ...o ...r |
00000070 c1 80 a9 6c 20 c1 80 a9 64 20 c1 80 a9 21 20 c1 |...l ...d ...! .|
00000080 80 60 a9 01 20 97 80 a9 38 20 97 80 a9 0f 20 97 |.`.. ...8 .... .|
00000090 80 a9 06 20 97 80 60 48 20 12 81 fa ad 81 7f 29 |... ..`H ......)|
000000a0 f8 8d 81 7f 8e 80 7f a2 ff 8e 82 7f 09 01 8d 81 |................|
000000b0 7f 29 f8 8d 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f |.)..............|
000000c0 60 48 20 12 81 fa ad 81 7f 29 fc 09 04 8d 81 7f |`H ......)......|
000000d0 8e 80 7f a2 ff 8e 82 7f 09 05 8d 81 7f 29 f8 8d |.............)..|
000000e0 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f 60 ad 81 7f |............`...|
000000f0 a9 00 8d 82 7f 29 fa 09 02 8d 81 7f 09 03 8d 81 |.....)..........|
00000100 7f ae 81 7f 29 f8 8d 81 7f 8a 29 7f a2 ff 8e 82 |....).....).....|
00000110 7f 60 ae 81 7f 8a a9 00 8d 82 7f 29 fa 09 02 8d |.`.........)....|
00000120 81 7f 09 03 8d 81 7f aa ad 80 7f 89 80 d0 e6 8a |................|
00000130 29 f8 8d 81 7f a9 ff 8d 82 7f 60 a9 00 8d 81 7f |).........`.....|
00000140 a9 00 8d 80 7f a9 ff 8d 83 7f a9 ff 8d 82 7f a9 |................|
00000150 cc 8d 8c 7f 60 00 00 00 00 00 00 00 00 00 00 00 |....`...........|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Weird Assembler Issue
kellymcdonald78 wrote:
;PURPOSE - This is the code which will written to ROM at $0000 (but will be referenced as $8000)...
Code: Select all
;
;
;The first difference we'll see is the inclusion of other source files (note they do not have .s extensions, we do not want
;them assembled as their own objects).
; ca65 documentation: https://cc65.github.io/doc/ca65.html#ss11.66
;
;Include the via import file (defining the imports there and keeping this source clean)
.include "via.s_imports"
;Include the acia (serial) import file
.include "acia.s_imports"
;Include the reset and interrupt vector definitions
.include "reset.s_interrupts"
.include "lcd.s_imports"
.code
setmode:
ldx #$FF
txs
clc ; Clear carry to set addition mode
xce ; Switch to native mode
sei ; Disable interrupts
cld ; Clear decimal mode
; Now in native mode with interrupts disabled and stack set
sep #%00110000 ; Set to 8-bit accumulator and index registers
jsr via_init ;Initialize VIA
jsr acia_init ;Initialize ACIA (serial)
jsr lcd_init ;Initialize LCD
jsr print_hello ;Print "Hello, World!" to the LCD
main:
nop ; dummy instruction
nop ; dummy instruction
nop ; dummy instruction
lda #'H'
jsr acia_putchar
jmp main ; Infinite loop to keep the program running;
00000000 9c 91 7f a9 1a 8d 93 7f a9 19 8d 92 7f 60 aa 8e |.............`..|
00000010 90 7f 84 ff 88 d0 fd 60 a9 08 2c 91 7f f0 fb ad |.......`..,.....|
00000020 90 7f 60 18 fb 78 d8 e2 30 20 3b 81 20 00 80 20 |..`..x..0 ;. .. |
00000030 82 80 20 40 80 ea ea ea a9 48 20 0e 80 4c 35 80 |.. @.....H ..L5.|
00000040 a9 48 20 c1 80 a9 65 20 c1 80 a9 6c 20 c1 80 a9 |.H ...e ...l ...|
00000050 6c 20 c1 80 a9 6f 20 c1 80 a9 2c 20 c1 80 a9 20 |l ...o ..., ... |
00000060 20 c1 80 a9 57 20 c1 80 a9 6f 20 c1 80 a9 72 20 | ...W ...o ...r |
00000070 c1 80 a9 6c 20 c1 80 a9 64 20 c1 80 a9 21 20 c1 |...l ...d ...! .|
00000080 80 60 a9 01 20 97 80 a9 38 20 97 80 a9 0f 20 97 |.`.. ...8 .... .|
00000090 80 a9 06 20 97 80 60 48 20 12 81 fa ad 81 7f 29 |... ..`H ......)|
000000a0 f8 8d 81 7f 8e 80 7f a2 ff 8e 82 7f 09 01 8d 81 |................|
000000b0 7f 29 f8 8d 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f |.)..............|
000000c0 60 48 20 12 81 fa ad 81 7f 29 fc 09 04 8d 81 7f |`H ......)......|
000000d0 8e 80 7f a2 ff 8e 82 7f 09 05 8d 81 7f 29 f8 8d |.............)..|
000000e0 81 7f a9 00 8d 80 7f a9 ff 8d 82 7f 60 ad 81 7f |............`...|
000000f0 a9 00 8d 82 7f 29 fa 09 02 8d 81 7f 09 03 8d 81 |.....)..........|
00000100 7f ae 81 7f 29 f8 8d 81 7f 8a 29 7f a2 ff 8e 82 |....).....).....|
00000110 7f 60 ae 81 7f 8a a9 00 8d 82 7f 29 fa 09 02 8d |.`.........)....|
00000120 81 7f 09 03 8d 81 7f aa ad 80 7f 89 80 d0 e6 8a |................|
00000130 29 f8 8d 81 7f a9 ff 8d 82 7f 60 a9 00 8d 81 7f |).........`.....|
00000140 a9 00 8d 80 7f a9 ff 8d 83 7f a9 ff 8d 82 7f a9 |................|
00000150 cc 8d 8c 7f 60 00 00 00 00 00 00 00 00 00 00 00 |....`...........|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|As for your program’s intro, I would write it thusly...
Code: Select all
setmode: sei ;no IRQs
sec ;default the...
xce ;MPU
clc ;return to...
xce ;native mode
cld ;binary arithmetic
...etc...Your method of initializing the 65C816 is always assuming the MPU is in emulation mode. That would be the case if powering on or if a hard reset occurs. However, if your code was called some time after the system came up, such as via a jump into the reset handler, the MPU will already be in native mode. If so, you can’t assume the width of the registers. Blindly loading $FF into .X without considering the present MPU state could be fatal if the index registers are set wide.
Also, the very first thing a reset handler should do is disable IRQ servicing. Yes, that is automatic if coming out of a hard reset (so is reversion to binary arithmetic). Your reset sequence is switching from emulation to native mode while IRQs are enabled, which depending on what the system was doing when jumping to the reset code, may not result in a pleasant outcome.
Lastly, it is generally not good programming practice to bury “magic numbers,” such as the new stack pointer value, in your code. Such constants should be defined in an INCLUDE file. This is especially relevant with the 65C816, since both its direct page and hardware stack can be almost anywhere in bank $00 address space, with either or both being changed by local code within functions. By defining the global values for DP and SP and using them to reset those registers as required, you avoid the risk of a typo at some point going undetected and setting the stage for an insidious bug. It’s part of the general process of defensive programming.
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Weird Assembler Issue
(Welcome, kellymcdonald78!)
-
kellymcdonald78
- Posts: 3
- Joined: 04 Jan 2026
Re: Weird Assembler Issue
Quote:
Code: Select all
setmode: sei ;no IRQs
sec ;default the...
xce ;MPU
clc ;return to...
xce ;native mode
cld ;binary arithmetic
...etc...Also, the very first thing a reset handler should do is disable IRQ servicing. Yes, that is automatic if coming out of a hard reset (so is reversion to binary arithmetic). Your reset sequence is switching from emulation to native mode while IRQs are enabled, which depending on what the system was doing when jumping to the reset code, may not result in a pleasant outcome.
Lastly, it is generally not good programming practice to bury “magic numbers,” such as the new stack pointer value, in your code. Such constants should be defined in an INCLUDE file. This is especially relevant with the 65C816, since both its direct page and hardware stack can be almost anywhere in bank $00 address space, with either or both being changed by local code within functions. By defining the global values for DP and SP and using them to reset those registers as required, you avoid the risk of a typo at some point going undetected and setting the stage for an insidious bug. It’s part of the general process of defensive programming.
The weird thing is, even after I make these changes and rebuild the binary file, the hex dump still doesn't match
e.g. I'm still getting
00000000 9c 91 7f a9 1a 8d 93 7f a9 19 8d 92 7f 60 aa 8e |.............`..|
Maybe I just need to reboot everything
Re: Weird Assembler Issue
My guess is that one of the include files has executable code or there's a system init file that gets inserted before your code. The funny thing is, your "setmode" code is nowhere in the hex dump you provided. A2 FF 9A ...
An alternative hypothesis: If the hex dump is a separate output file, check the file date/time to make sure you are looking at the current hex dump file. It might be going to another folder.
Daryl
An alternative hypothesis: If the hex dump is a separate output file, check the file date/time to make sure you are looking at the current hex dump file. It might be going to another folder.
Daryl
Please visit my website -> https://sbc.rictor.org/
Re: Weird Assembler Issue
Greetings,
Friend is using a cc65 based devcontainer: https://github.com/dhirsch1138/cc65_template
8BIT is right on the nose; the make file(s) for link the files in alphabetical order so the bin reflects flat. This is harmless, so long as you don't try to statically address rom addresses yourself (let the linker do that for you). There are several ways reference code in different files, but a simple way is to add more segments. Here is an example that has code segments in many files https://github.com/dhirsch1138/Shrimpy_ ... er.cfg#L38
Friend is using a cc65 based devcontainer: https://github.com/dhirsch1138/cc65_template
8BIT is right on the nose; the make file(s) for link the files in alphabetical order so the bin reflects flat. This is harmless, so long as you don't try to statically address rom addresses yourself (let the linker do that for you). There are several ways reference code in different files, but a simple way is to add more segments. Here is an example that has code segments in many files https://github.com/dhirsch1138/Shrimpy_ ... er.cfg#L38
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Weird Assembler Issue
NeonGuppy wrote:
Greetings,
Friend is using a cc65 based devcontainer: https://github.com/dhirsch1138/cc65_template
8BIT is right on the nose; the make file(s) for link the files in alphabetical order so the bin reflects flat. This is harmless, so long as you don't try to statically address rom addresses yourself (let the linker do that for you). There are several ways reference code in different files, but a simple way is to add more segments. Here is an example that has code segments in many files https://github.com/dhirsch1138/Shrimpy_ ... er.cfg#L38
Friend is using a cc65 based devcontainer: https://github.com/dhirsch1138/cc65_template
8BIT is right on the nose; the make file(s) for link the files in alphabetical order so the bin reflects flat. This is harmless, so long as you don't try to statically address rom addresses yourself (let the linker do that for you). There are several ways reference code in different files, but a simple way is to add more segments. Here is an example that has code segments in many files https://github.com/dhirsch1138/Shrimpy_ ... er.cfg#L38
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Weird Assembler Issue
The OP is using the assembler and linker from the cc65 toolchain, as provided by a so-called dev container. That's a docker container to run development software as I understand it.
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Re: Weird Assembler Issue
You are correct fachat. Devcontainers are reproducible development environments; defined in structured json file(s) which are used do build docker images when deployed.
* You can store and share them as git repos, either as templates (https://github.com/dhirsch1138/cc65_template) or full projects (https://github.com/dhirsch1138/Shrimpy_BenEater_6502)
* By keeping everything in a repository (both the code and the devcontainer definition), it makes everything super portable and easy to stand up.
* And since the dev environ is in the container, it doesn't clutter the rest of your system. You can have access to whatever you need even if your system doesn't support those packages natively.
I'm a fan.
* You can store and share them as git repos, either as templates (https://github.com/dhirsch1138/cc65_template) or full projects (https://github.com/dhirsch1138/Shrimpy_BenEater_6502)
* By keeping everything in a repository (both the code and the devcontainer definition), it makes everything super portable and easy to stand up.
* And since the dev environ is in the container, it doesn't clutter the rest of your system. You can have access to whatever you need even if your system doesn't support those packages natively.
I'm a fan.
Re: Weird Assembler Issue
To kellymcdonald78,
Did you resolve this issue?
Daryl
Did you resolve this issue?
Daryl
Please visit my website -> https://sbc.rictor.org/