• Please review our updated Terms and Rules here

Assembly Language question: odd JMP behavior in boot1

mlemmert11

Member
Joined
Oct 28, 2015
Messages
40
I am doing some boot tracing on an Apple IIe and in boot1 I’ve encountered an indirect jump to ($003E) at $836 which I’m struggling to understand. I’m a beginner at assembly language so I think I may be missing something fundamental that may be obvious to a more experienced assembly programmer.

I’ve read a walkthrough of the Apple II boot process and it says that $836 is where sectors are read in and that $84A is the jump out to boot2.

Two screen shots are attached with the exact boot1 code I’m looking at.

Here is what is puzzling to me:

1) $84A jump doesn’t behave as expected

After copying boot0 to $9600, and boot1 to $9800, I put jump to the monitor at $984A and ran boot0 and boot1, which resulted in the disk in the drive booting up completely (i.e. I see the intro screen. The disk I’m using is Multi-Disk Catalog), which makes me think that the information I read about the $84A jump out to boot2 either isn’t accurate for the Apple IIe or I misunderstood something in that write-up.


2) $836 JMP ($003E) indirect jump doesn’t behave as expected

I started putting in breaks before $984A, then running boot1, until I found the location at which the disk in the drive doesn’t fully boot up and returns control to the monitor. That location is $836.

I put a break in directly before, at $835, and then looked at the values in $003E and $003F, and those values are 3E and 00 respectively, which made me think that the indirect jump is actually jumping to $003E.

However, I looked at the code around $003E and it has a break immediately at $0040. If there is a break I’m stumped at how the disk in the drive is booting up completely if the execution really does jump to $003E.

If I jump to $003E from any other location (for example I tried a one-line test Jump to $003E at $9500) then $003E runs as expected and breaks at $0040.

This leads me to think that the boot1 code prior to $836 somehow alters something in the system so that $836 JMP ($003E) somehow jumps to somewhere other than the address stored in $003E and $003F, but I’m totally stumped as to what the system is doing to cause it.


Does anyone have any ideas on the behavior I described on the $84A jump to boot2 and the $836 indirect jump?

I really appreciate any insights anyone has!

9800 code (1 of 2).jpg9824 code (2 of 2).jpg
 
What OS are you booting? If I have it I'll hook up my HP1611A logic analyzer and look at the trace for you.

Side note:

The indirect jump was an early method of obfuscating code. Many games would load completely from disk and be completely in memory. Sometimes code would be placed in locations that would be over written my the Apple monitor. The old Asteroids game was easy to find in memory after hitting reset. The program would crash after an indirect jump to a zero page location used by the monitor. This was the first of many games we cracked ( back in the day ) with the colleges HP1611A. It allowed us to see what values were in these zero page locations and replace them with a few lines of code before JMPing to the start of the program.
 
What OS are you booting? If I have it I'll hook up my HP1611A logic analyzer and look at the trace for you.

Side note:

The indirect jump was an early method of obfuscating code. Many games would load completely from disk and be completely in memory. Sometimes code would be placed in locations that would be over written my the Apple monitor. The old Asteroids game was easy to find in memory after hitting reset. The program would crash after an indirect jump to a zero page location used by the monitor. This was the first of many games we cracked ( back in the day ) with the colleges HP1611A. It allowed us to see what values were in these zero page locations and replace them with a few lines of code before JMPing to the start of the program.


Thanks a lot for the reply and your offer of assistance, I really appreciate it! Sorry it took me a bit to reply back, I didn't get an email alert to the posting for some reason.

The OS I'm booting is DOS 3.3. The behavior I describe happens at the same exact boot1 memory location ($836) whether I'm booting the DOS 3.3 master disk or a variety of other software using DOS3.3.

What you describe sounds very much like the symptoms of what I'm encountered: an indirect jump using a zero page address ($3E) and the value of that zero page address appears to be hidden. Is there any other information I can provide that would be helpful for you in running the trace?

On a side note, I can see why commercial software would want to obfuscate things, but do you know why the ROM boot up process would try to be so "sneaky"?


Thanks again.
 
It sounds like you may have a bad RAM chip.

Thanks for the reply! Very interesting on the ROM chip. I hadn't considered that but I could easily be missing something as my hardware knowledge isn't very advanced.

If you have an Apple IIe, would you be willing to boot it up and check the value at $836 and see what is there?

For quick reference if helpful, here is the command sequence to get exactly to where I'm at, after turning on the drive with any DOS 3.3. disk:

1) Control Reset
2) Call -151
3) 9600<C600.C6FFM ; (move boot1 into RAM)
4) 96FA:98; (jump to the monitor after loading boot1 at $800.$8FF

From here if you do a $824L you should see the disassembled code at $836, which I'm seeing as JMP ($003E)

On a side note, if the ROM chip is bad, do you think it makes sense that the code at $800 would execute successfully run (it does for me; 800G after step 4 above fully boots up the disk in the drive)? i.e. if the value stored in ROM for the indirect location is bad, wouldn't it also be bad when the code is executed?


Thanks for your help!
 
You can do the same for yourself... with any emulator. I did it with AppleWin (I added step 5, 9600G), and I see JMP ($003E) at $836.

Thanks, didn't realize that, I haven't used an emulator in ages. Thanks for checking on your system too!
 
I am assuming you don't have any diagnostic software?

No, I don't have any diagnostic software. Is there any in particular you'd recommend other than the HP Analyzer tool you mentioned before?


In any event, I think I figured it out what's going on.

The value at $003E & $003F are being changed by the boot code as it runs. However, the new values are not visible through the monitor. I was able to proof that out by loaded $003E & $003F to the accumulator and the X-register after the point in the code where the values are changed. The new values are observable when loaded into the registers. I was able to further proof the theory by putting a break at the true location.

Have you every seen or heard of anything like that before? I'm suspicious it has something to do with $3E & $3F being in page zero.
 
Last edited:
There are many diagnostic programs and even a diagnostic pluggin card ( I have two ). Apple put out ones for the II, //e and //c. I could try to make a DSK file of one.
 
There are many diagnostic programs and even a diagnostic pluggin card ( I have two ). Apple put out ones for the II, //e and //c. I could try to make a DSK file of one.

Thanks for the information. Are there any that you think would be out there on asimov, etc? If not and you're up for trying to make the DSK file that sounds great. Much appreciated.
 
And no wonder: the monitor uses 3e and 3f. They won't be reliable by the time you're examining them.

http://stason.org/TULARC/pc/apple2/...o-Page-locations-are-likely-to-be-in-use.html

There it is. Thanks!

I actually found that chart while troubleshooting and glanced at it quickly (too quickly), and got the high order and low order nibble mixed up, so it looks like just Applesoft used that address, which of course wasn't loaded at the time, so I moved on to other theories at the time.

That really does make sense. I tried modifying a few other of the address used by the monitor and some exhibit the same behavior and some don't.

Thanks for all your and pcjunk's help. It makes all the difference being able to bounce some ideas around.
 
I came across this thread by a total coincidence and could not resist jumping in to "solve" this "mystery".

You have so far correctly deduced what's happening: the second stage boot (first stage is Disk ][ ROM code which loads T$0, S$0 @ $0800) at $0800 loads the rest of the DOS from I think $9C00 through $BFFF and then does an indirect jump to $08FD, which means it is taking the address at $08FD-08FE and jumping to that address. I forget the address that ends up in $08FD-08FE after DOS is done loading but it's somewhere in $96xx, or maybe $9Bxx (it's been a while since I did any boot tracing ;)).

In the meantime, the indirect jump to $3E-3F is jumping back into the disk controller ROM to load another sector, then jumps back to $0801, and keeps going back and forth like this until the counters indicate the next stage of DOS is loaded and ready to execute.

To know where the code is jumping to once the next stage of DOS is loaded, you want to modify the first stage boot so that it modifies the second stage boot so that when the latter is done loading DOS it returns control to you via the monitor so you can see what's in $08FD-08FE.

This is how I used to do it (from memory, and I have no Apple ][ in front of me presently, so please forgive if there are mistakes, you should be able to noodle it out if there are):

First, copy boot ROM and modify:

4600<C600.C6FFM
46F8: A9 4C 8D 4A 08 A9 69 8D 4B 08 A9 FF 8D 4C 08 4C 01 08

LDA $#4C ; JMP (direct) opcode
STA $084A ; modify the indirect ($6C) JMP to a direct JMP
LDA $#69 ; address lo-byte
STA $084B ; set direct address lo-byte
LDA $#FF ; address hi-byte
STA $084C ; set direct address hi-byte
JMP $0801 ; do second stage boot

So now second stage boot will jump to $FF69 when it's done loading the next boot stage of DOS.

Now execute:

4600G

When control is returned, look at $08FD-08FE to find your jump vector into DOS, which loads the rest of DOS from tracks $00-$02, then jumps to initialization, and finally runs "HELLO".

Again, all from memory, so apologies if there is a mistake or two in there, but I think I got it mostly right. I did this a million times back in the day but I had to use your screen shots to refresh my recollection.

I'll check back in to see if any follow-up is required.
 
Last edited:
I came across this thread by a total coincidence and could not resist jumping in to "solve" this "mystery".


4600<C600.C6FFM
46F8: A9 4C 8D 4A 08 A9 69 8D 4B 08 A9 FF 8D 4C 08 4C 01 08

LDA $#4C ; JMP (direct) opcode
STA $084A ; modify the indirect ($6C) JMP to a direct JMP
LDA $#69 ; address lo-byte
STA $084B ; set direct address lo-byte
LDA $#FF ; address hi-byte
STA $084C ; set direct address hi-byte
JMP $0801 ; do second stage boot

So now second stage boot will jump to $FF69 when it's done loading the next boot stage of DOS.

Now execute:

4600G

When control is returned, look at $08FD-08FE to find your jump vector into DOS, which loads the rest of DOS from tracks $00-$02, then jumps to initialization, and finally runs "HELLO".

Thank you very much for your help!!!

Your memory was exactly correct! The commands you provided worked as predicted and I was returned to the monitor prompt after the 2nd boot phase. The problem with my code turned out to be that I was copying 4800<800.8FFM and then modifying it at $4800, but there is a jump back to $801 after the read sector routine. Once I saw your code work I was able to pinpoint this and proof it by fixing that jump to go back to $4801 and get the same result.

Two follow-up questions for you if you have time.


==QUESTION 1

I was originally trying to follow a boot tracing example in the magazine Softkeys volume 2, which used the utility program Multi-Disk Catalog as the disk in the drive (though I think any would work as long as it didn’t have a modified RWTS).

Knowing what I know now from your advice and my studying of the code for many hours, I don’t see how their method could possibly have worked. I’m curious if you have any idea? My best guess is that the soft keys were designed for use with an original Apple II (the article says 48k Apple II required, no II+ or IIe designation mentioned) and that the ROM boot code is step a little differently on those systems. I tried using an emulator to check that guess but everything looks the same on an Apple II and Apple II+ as it does on my physical IIe. The only wild card I see in that test is I’m not 100% sure I’ve got the right ROM for the original Apple II; I’ve never seen one of those systems and it wasn’t very clear what file name on asimov was for the original Apple II.


Here is the full command sequence in the magazine:

9600<C600.C6FFM
96FA:98
9801: 4C 59 FF
9600G
C0E8

This part worked fine. It split your method into two phases, with this being the first which gets the 2nd boot phase loaded into $800. But what comes next is where things stop making sense….

9800<800.8FFM

9843:93
9301:4C 59 FF

these two line are supposed to change a jump out to $301 to jump to $9301, but there is no jump to $301 at that location. And $9843 already has the value $93 before exacting their command.

9805:98 This is supposed to fix the code to work in $9800 range, but all it does is screw up the BNE at $9805 which modified the high order byte of it’s operand from $08 to $98 all on it’s own after the memory copy.

9600G
C0E8

All these commands do is result in the disk fully booting for what seem to be completely explainable reasons.


==QUESTION 2


I’m working on acquiring the necessary knowledge to get into some serious Apple II assembly language game programming. Things are going pretty well with tracking down the information on the key logical areas, like graphics addresses, RWTS parameters, etc. I have some experience with this but this would be my first time in assembly.

There is only one issue I’m nervous about (so far) and that is memory management. My understanding is that real quality 1980s Apple game pushed the system to it’s limits, especially in terms of memory. In particular, my understanding it that it was pretty common for game disks to skip loading DOS in order to save memory. From the memory maps, I can totally see why.

The two implications I can see from that (so far) are a) needing to do read/write of game data via RWTS directly instead of the DOS file manager subroutines and b) that the disk somehow needs to boot without DOS.

I think I know where to start with the RWTS part, I’ve found some great info online, but I was wondering if you have any suggestions on how to accomplish booting a 5.25” disk without DOS and launching an assembly language program? Any information would help and be much appreciated, whether it be conceptual, suggested reading, or anything.

My best guess is that I need to write some machine language code to disk on some particular tracks, which are executed by the boot ROM of the disk, after the boot ROM of the disk is executed by the computer ROM boot process we were just discussing. I’d envision the machine code at that special disk location would jump to the entrance to my program. Based on the DOS comments in your post, it sounds that special location may be tracks $00-$02.


Thanks a lot for any thoughts you can offer!
 
Last edited:
==QUESTION 1

I was originally trying to follow a boot tracing example in the magazine Softkeys volume 2, which used the utility program Multi-Disk Catalog as the disk in the drive (though I think any would work as long as it didn’t have a modified RWTS).

Knowing what I know now from your advice and my studying of the code for many hours, I don’t see how their method could possibly have worked. I’m curious if you have any idea? My best guess is that the soft keys were designed for use with an original Apple II (the article says 48k Apple II required, no II+ or IIe designation mentioned) and that the ROM boot code is step a little differently on those systems. I tried using an emulator to check that guess but everything looks the same on an Apple II and Apple II+ as it does on my physical IIe. The only wild card I see in that test is I’m not 100% sure I’ve got the right ROM for the original Apple II; I’ve never seen one of those systems and it wasn’t very clear what file name on asimov was for the original Apple II.


Here is the full command sequence in the magazine:

9600<C600.C6FFM
96FA:98
9801: 4C 59 FF
9600G
C0E8

This part worked fine. It split your method into two phases, with this being the first which gets the 2nd boot phase loaded into $800. But what comes next is where things stop making sense….

9800<800.8FFM

9843:93
9301:4C 59 FF

these two line are supposed to change a jump out to $301 to jump to $9301, but there is no jump to $301 at that location. And $9843 already has the value $93 before exacting their command.

9805:98 This is supposed to fix the code to work in $9800 range, but all it does is screw up the BNE at $9805 which modified the high order byte of it’s operand from $08 to $98 all on it’s own after the memory copy.

9600G
C0E8

All these commands do is result in the disk fully booting for what seem to be completely explainable reasons.

Yeah, I have no idea what they were thinking/doing. I'd have to see the whole article. Sometimes those magazines were frustratingly error prone with articles about this sort of thing. Keeping on top of all those hex bytes can be difficult for editors.

==QUESTION 2


I’m working on acquiring the necessary knowledge to get into some serious Apple II assembly language game programming. Things are going pretty well with tracking down the information on the key logical areas, like graphics addresses, RWTS parameters, etc. I have some experience with this but this would be my first time in assembly.

A good book for that (if you can finda copy) is "Apple Garphics & Arcade Game Design" by Jeffrey Stanton:

http://www.amazon.com/Apple-Graphics-Arcade-Game-Design/dp/0912003014

I think you can find a copy for less than the $599 presently advertised.

Note: the assembly listings in the book have errors. I typed them in at one point and they didn't work. Not discounting the possibility I inserted a typo but I'm pretty sure I double checked. Just an FYI...

There is only one issue I’m nervous about (so far) and that is memory management. My understanding is that real quality 1980s Apple game pushed the system to it’s limits, especially in terms of memory. In particular, my understanding it that it was pretty common for game disks to skip loading DOS in order to save memory. From the memory maps, I can totally see why.

The two implications I can see from that (so far) are a) needing to do read/write of game data via RWTS directly instead of the DOS file manager subroutines and b) that the disk somehow needs to boot without DOS.

I think I know where to start with the RWTS part, I’ve found some great info online, but I was wondering if you have any suggestions on how to accomplish booting a 5.25” disk without DOS and launching an assembly language program? Any information would help and be much appreciated, whether it be conceptual, suggested reading, or anything.

My best guess is that I need to write some machine language code to disk on some particular tracks, which are executed by the boot ROM of the disk, after the boot ROM of the disk is executed by the computer ROM boot process we were just discussing. I’d envision the machine code at that special disk location would jump to the entrance to my program. Based on the DOS comments in your post, it sounds that special location may be tracks $00-$02.

It's simple, really. Most early games that loaded once had their own boot loader (particularly since the disk was copy protected so a special boot loader was necessary). A small RWTS routine was usually loaded from the first few sectors of track 0, then the rest of the game loaded into memory from the rest of the disk and then control passed to it. For more complex games they either used DOS 3.3 (normally a modified version for copy protection), ProDOS (in later years) or a custom DOS entirely to thwart pirates (Sir-Tech had RDOS and Broderbund had their extremely clever 18-sector DOS).

I once wrote a boot loader. I copied the routines to move the head from track to track from DOS 3.3 RWTS and then the rest was just putting up a splash page and reading in the sectors from the disk and then jumping to the start of the (pirated) program. Sectors were read using the Disk ][ ROM code, just like all DOS loaders. It was trivial, once you've mastered assembly/machine language :)
 
Thanks a lot for your follow-up reply!


Yeah, I have no idea what they were thinking/doing. I'd have to see the whole article. Sometimes those magazines were frustratingly error prone with articles about this sort of thing. Keeping on top of all those hex bytes can be difficult for editors.

Ok, thanks. I'm glad to know that I'm probably not just crazy :) I had never worked with those articles back in the day so I had no frame of reference as to what to expect.


A good book for that (if you can finda copy) is "Apple Garphics & Arcade Game Design" by Jeffrey Stanton: Note: the assembly listings in the book have errors.

Thanks for the recommendation! (and the foreword about the errors). I just purchased a copy of "High-resolution Graphics and Animation Using Assembly Language" by Leonard Malkin, but haven't received it yet. Are you familiar with that book? If so, do you think it's worth buying both?



It's simple, really. Most early games that loaded once had their own boot loader (particularly since the disk was copy protected so a special boot loader was necessary).

Since I'm not concerned about copy protecting anything I write, do you think I could simplify this and just use the stock RWTS that loaded from computer ROM? For example, the "boot loader" at track 0 on the disk would use the "stock" RWTS to load the game into memory and pass control to the game?

I once wrote a boot loader. I copied the routines to move the head from track to track from DOS 3.3 RWTS and then the rest was just putting up a splash page and reading in the sectors from the disk and then jumping to the start of the (pirated) program. Sectors were read using the Disk ][ ROM code, just like all DOS loaders. It was trivial, once you've mastered assembly/machine language :)

You clearly are very knowledgable! Thanks so much for sharing your insights.

Learning 6502 assembly/machine language and writing an RPG has been a life long goal for me. I never tackled assembly as a kid in the 1980s, I got distracted by modems and data communications and ended up in the BBS world, then ISP. Anyway, I really appreciate the support of this forum, getting a key insights can make all the difference. I hope to be able to pay it forward as my knowledge level increases.
 
Back
Top