August 17th, 2010

Some Assembly Required: Incremental Progress

In this installment, we’re going to continue to learn more about the three primary registers in the 6502 processor (accumulator, X, and Y). We’ll also create our first simple subroutine.

You can [Download not found] for this program.


Before we do anything else, let’s take a moment to talk about comments. Comments are text in your source code that are human-readable, intended to help you remember what your code is doing (and so others can read your code more easily).

There are two formats for comments. Comments starting with a semicolon (“;”) can be placed stand-alone on a line of code, or can be at the end of any line of code. Comments starting with an asterisk (“*”) can only be placed on a line by themselves. In both cases, the comment extends from the character that starts the comment to the end of the line.

We’ve been using these already, but it just occurred to me that I haven’t actually talked about them yet, so there you go.

Our First Subroutine

Let’s start by creating our first subroutine. This simple routine just takes the value in the X register and prints it to the screen, followed by a carriage return. We’ve used the PRBYTE and CROUT firmware routines in the past, so we won’t dwell on them.

Let’s look at the code:

* xcr
* Prints the byte in X then a carriage return.
xcr      start
         txa                            ;Copy X to A
         jsr   PRBYTE                   ;Print the byte in A
         jsr   CROUT                    ;Print CR
         rts                            ;Return to caller

The first thing this code does is use the implied mode instruction TXA (Transfer X register to Accumulator) to copy the value in the X register into (believe it or not) the accumulator. We do this because the PRBYTE firmware routine prints the value in the accumulator, but we want to use the X register in this case.

Then we call CROUT to output a carriage return, and use RTS to return to the caller.

Incrementing and Decrementing

A very common operation is the need to add or subtract one from a number. For this reason, the 6502 has special instructions just for that purpose. This time, we’re going to look specifically at incrementing and decrementing the index registers.

The INX (INcrement X register) and INY (INcrement Y register) instructions add one to the value of the respective registers. Similarly, DEX (DEcrement X register) and DEY (DEcrement Y register) subtract one from these registers.

Let’s take a look at a code sample:

* Demo increment and decrement

         ldx   #$00                     ;Start with zero
         jsr   xcr                      ;Print it
         inx                            ;Increment X
         jsr   xcr                      ;Print it
         dex                            ;Decrement X
         jsr   xcr                      ;Print it
         dex                            ;Oooh, now what?
         jsr   xcr                      ;Print that

We start by setting the X register to zero and calling our xcr routine to print that value to the screen.

Then we increment X and print the resulting value (in this case, $01).

Then we decrement X and print the result again (this time, $00).

Now, let’s see what happens when you decrement the X register again. The result is $FF (255). That’s right, they wrap around. if you then incremented X again, the result would wrap back to $00.

This is called carry, and it’s similar to what you do when you’re doing addition and subtraction by hand. You have to carry the result from one column to the next when adding or subtracting by hand; similarly, when doing math byte by byte, you have to carry the result from one byte to the next.

We’ll be looking in more detail as to how the carry bit works and how to perform multi-byte mathematics later.

Next Time

Next time, we’re going to apply this knowledge about incrementing and decrementing values to build our first loop to repeat an operation several times until the desired result is achieved.

July 18th, 2010

Sweet16 Apple IIgs emulator version 2.2 released

Sweet16 2.2 for Mac OS X has been released; this is the latest version of Eric Shepherd and F.E. Systems’ Apple IIgs emulator for Mac OS X.

One of the key changes is that by default, Sweet16 now limits the emulated IIgs speed to 40 MHz. Previously, the default was to go as fast as possible. This resulted in using 100% of at least one CPU core, which would cause battery drain and temperature issues, especially on laptops. Although users always had the option to turn on speed control and throttle the speed, this wasn’t obvious, so to help out new users, the default was changed.

If you’re already using Sweet16, your current setting won’t change when you update to version 2.2. If you’re a current user and are having this problem, you can enable speed control by opening the preferences, going to the CPU tab, and turning on the “Speed control” option. Then select a speed to throttle your emulated IIgs to.

Since modern Macs can typically blaze along at over 100 MHz emulated IIgs speed if unthrottled, even setting it to 40 MHz should improve the situation dramatically.

The full change list:

1. Sweet16 now defaults to having speed control enabled, with the GS set to a 40 MHz emulated speed. This prevents laptops from getting hot while running Sweet16. You can easily turn off speed control to let your GS fly, using the preferences’ CPU options panel.

2. You can now mount ProDOS-order (.po) disk images that are not floppy disk sizes.

3. When paused, Sweet16 no longer continues to use lots of your Mac’s processor capacity.

4. Creating 1.4 MB disks using the Create Disk Image feature now creates disk images that are actually 1.4 MB, rather than 1.6 MB.

July 1st, 2010

Some Assembly Required: Introducing the Registers

Unlike most modern processors, the 6502 series of processors has only three primary registers that you can use for manipulating data. A register is, basically, a slot within the processor that can contain a numeric value. On the 6502 and 65C02, these are each able to hold an 8-bit value. On the 65816, they can hold either 8-bit or 16-bit values, depending on whether or not the processor is switched to use 16-bit values for the register in question.

The accumulator — also known as the “A” register — is used for performing computations. Addition, subtraction, binary operations, and so forth are all performed on the accumulator.

The other two registers, X and Y, are called index registers. These registers are primarily used to index into a block of data while performing operations.

Addressing Modes: An Introduction

When you think about it, there are several ways to reference information. You can load or store a value directly into a specific memory address. You can set a register’s value to a specific number. You can use the address stored in a memory location as the address from which to load a value. These, among others, are called addressing modes. We’ll be introducing these gradually as we proceed through this series of articles.

Immediate Addressing

The first, and simplest, addressing mode is immediate mode. Immediate addressing is when you load a specific numeric value into a register. For example, here’s how you can set the value of the accumulator to zero:

            lda      #0

This is pretty straightforward. The LDA instruction (“LoaD Accumulator”) is used to load a value into the accumulator. When you want to represent an immediate numeric constant value in assembly language, you put a pound sign (“#”) in front of it.

Similarly, you can load immediate values into the X and Y registers like this:

            ldx      #$55
            ldy      #32

The LDX (“LoaD X register”) and LDY (“LoaD Y register”) instructions work exactly like LDA. Note, however, the presence of the dollar sign (“$”) in the LDX instruction above. That indicates that the value is hexadecimal.

Absolute Addressing

Absolute addressing is the mode by which you load and store values to a specific address in memory. For example:

            lda      #$ED
            sta      $0300

This code snippet loads the hexadecimal number $ED into the accumulator, then stores it in memory at the address $0300 using the STA instruction (“STore Accumulator”). You can similarly use STX (“STore X register”) and STY (“STore Y register”) to save the values of the X and Y registers into specific memory locations.

You’ll note that these instruction names get recycled. This is the first key lesson of assembly language programming. The 6502 has only about 50 different instructions, but most of them are available in multiple addressing modes. This lets each instruction take on a variety of uses; we’ll learn more about these over time.

Calling Subroutines

Before we get to our sample program for the week, let’s quickly look at how you call subroutines in assembly language. A subroutine is a (usually short) subprogram that handles specific tasks.

To call a subroutine, you use the JSR (Jump to SubRoutine) instruction. For now, we’ll only look at how to use its absolute addressing mode version.

Subroutines return to the calling code using the RTS (ReTurn from Subroutine) instruction. This instruction accepts no arguments. This is, for future reference, the implied addressing mode.

Let’s put together a little sample that uses what we’ve learned this week (note that this is using ORCA/M 8-bit syntax):

         keep  Registers                ;Name to compile to

PRBYTE   gequ  $FDDA                    ;Prints a hex byte
CROUT    gequ  $FD8E                    ;Prints a CR

         org   $2000

main     start
         lda   #$AB                     ;Set A to the number $AB
         jsr   PRBYTE                   ;Print A
         jsr   CROUT                    ;And a carriage return
         rts                            ;Exit program

This is actually a simpler program than last week’s, but we’re going to look at it in more detail.

The KEEP directive on the first line is a bit of ORCA detail; it tells the assembler to save the assembled binary code in a file named “Registers”. This is not a 6502 operation, but a directive — or special instruction — for the assembler itself.

The next two lines use the GEQU (Global EQUate) directive define the constants PRBYTE and CROUT to point to two memory locations; these constants let us refer to these locations by name instead of number, which makes our code easier to read. These locations, in the Apple II ROM, represent a routine that prints the value of the accumulator as a hexadecimal number and a routine that simply prints out a carriage return character, respectively.

The ORG (ORiGin) directive tells the assembler the address in memory at which the program should load. In this case, we’re specifying $2000 (which happens to be the location in memory at which the high resolution graphics screen starts, but since our program doesn’t use that memory, it’s a nice place to run our code).

Next comes the body of our program. In ORCA, blocks of code are surrounded by the START and END directives. These allow us some capabilities we’ll explore later; for now, it suffices to know that you need to include them in ORCA but not in Merlin.

The main program uses the LDA instruction to set the accumulator’s value to the immediate value $AB, then calls the PRBYTE routine to print it to the screen. The CROUT routine is called next, to send a carriage return to the screen — this moves the printing cursor to the beginning of the next line.

Finally, our program ends with an RTS instruction. Simple 8-bit programs are called using a JSR instruction, so we return to the calling program (such as the ORCA shell or the BASIC interpreter) with an RTS.

Note for Merlin users: The GEQU directive in ORCA doesn’t work in Merlin; instead, you should use simply EQU. Likewise, you don’t need the KEEP, START, and END directives in Merlin. Instead, to specify the filename with which to save the assembled file, add “SAV REGISTERS” to the end of the source code file.

Save this code and assemble it, following the same instructions as last time. In ORCA, once you’ve saved the file, you can assemble and run it using the command “RUN REGISTERS.ASM” (assuming you saved the source code with the name “REGISTERS.ASM”).

Final Notes

You’ll notice we’ve skipped over any details on how the JSR and RTS instructions actually function together. This is a whole interesting set of information that we’re going to ignore for now, but we’ll get to it in a couple of installments.

Next time, we’ll expand on what we learned in this installment by doing some basic manipulation of the contents of registers.

June 21st, 2010

Some Assembly Required: Hello World

Among programmers, there’s a long-standing tradition whereby one’s first program in any given language is one that simply displays the message “Hello world.”

In this installment of Some Assembly Required, we’re going to create “Hello world.” I’m not going to really explain how it works this time around. We’ll get into understanding the programming next time. The goal, for now, is to simply learn the commands needed to build and run your programs, so we won’t have to deal with that later.

ORCA/M 4.1 (8-bit)

Let’s start by building our program for ORCA/M for 8-bit Apple IIs. Start by launching ORCA.SYSTEM, which will drop you into the ORCA command shell. Type “NEW” to start editing a new file, and press the Return key.

Once you’re in the editor, type in the following listing. Note that the editor is slightly unusual if you’re used to other editors; you’ll want to read through Chapter 3 of the ORCA/M manual to learn its commands.

If your computer is an older Apple II without support for typing lower-case letters, that’s fine, just use all upper-case instead.

COUT     gequ  $FDED                    ;The Apple II character output func.

         keep  HelloWorld

main     start
         ldx   #0                       ;Offset to the first character
loop     lda   msg,x                    ;Get the next character
         cmp   #0                       ;End of the string?
         beq   done                     ;->Yes!
         jsr   COUT                     ;Print it out
         inx                            ;Move on to the next character
         jmp   loop                     ;And continue printing
done     rts                            ;All finished!

msg      dc    c'Hello world.'
         dc    h'0D'
         dc    h'00'

Once you’ve finished entering the code, press control-Q to bring up the quit and save menu, then press “N” to save the file to a new name. Type “HelloWorld.asm” and press return, then press “E” to exit the editor.

Running the program is as simple as typing “RUN HelloWorld.asm”. This will compile, link, and run the program. If any errors occur, type “EDIT HelloWorld.asm” to open the file back up in the editor and find and fix any discrepancies between what you typed and the listing above, then try again.

ORCA/M (16-bit)

To build the program using the 16-bit version of ORCA/M (but still run it as an 8-bit program), start up the ORCA shell by launching ORCA.SYS16 from the Finder. At the command line, first type “ASM65816” to select the assembly code edit mode, then type “EDIT HelloWorld.asm” to start up the editor.

Enter the following code:

         65816 off
         65C02 off                      ;Use 6502 opcodes only

COUT     gequ  $FDED                    ;The Apple II character output func.

         keep  HelloWorld

main     start
         ldx   #0                       ;Offset to the first character
loop     lda   msg,x                    ;Get the next character
         cmp   #0                       ;End of the string?
         beq   done                     ;->Yes!
         jsr   COUT                     ;Print it out
         inx                            ;Move on to the next character
         jmp   loop                     ;And continue printing
done     rts                            ;All finished!

         msb   on
msg      dc    c'Hello world.'
         dc    h'8D'
         dc    h'00'

Once you’ve entered the code, press Command-S to save your work, then Command-Q to quit to the command line prompt. Type “CMPL HelloWorld.asm” to compile and link the program. If any errors occur, type “EDIT HelloWorld.asm” to edit the program and fix the problems, then try again.

Since this program is designed as an 8-bit program, to be run under ProDOS 8, but we’ve built it using the 16-bit version or ORCA, we need to do an extra step. We need to convert it from a GS/OS load file into a ProDOS 8 compatible binary file. To do this, type “MAKEBIN HelloWorld Hello”. This will take the compiled “HelloWorld” program and convert it into an 8-bit binary file named “Hello”.

Then you can quit the ORCA shell, start up Applesoft BASIC, use the PREFIX command to make your way into the directory containing the program, and type “BRUN HELLO” to run it.


These instructions are for Merlin 8/16+. Your mileage may vary somewhat on other versions of Merlin.

Once you’ve launched Merlin, press “F” to open the full-screen editor, then enter the following code.

            org       $2000

COUT        equ       $FDED         ;Apple II character out func.

            ldx       #0            ;Offset to first character
:loop       lda       msg,x         ;Get the next character
            cmp       #0            ;End of the string?
            beq       :done         ;->Yes!
            jsr       COUT          ;Print it out
            inx                     ;Move on to the next character
            jmp       :loop         ;And continue printing
:done       rts                     ;All finished!

msg         asc       "Hello world."
            dfb       $8D
            dfb       $00

            sav       Hello

Once you’ve entered the code, press Command-6 to save (Type “Hello” for the filename when prompted) and assemble and link your code. You should wind up with a binary file named “Hello” in the same directory as the source code file you just saved (which will be named “Hello.S”).

You can then switch to Applesoft BASIC, use the PREFIX command to make your way into the directory containing the program, and type “BRUN HELLO” to run it, and type “BRUN HELLO” to run the program.

That’s the gist of how to build a simple program in these three environments. Don’t worry about how this stuff works for now. We’ll start learning actual assembly language next time.

June 18th, 2010

Some Assembly Required: Choosing an Assembler

Over the coming weeks (or maybe months or even years), I’ll be posting a series of articles introducing you to the glorious, glamorous world of assembly language programming for the 6502 series of microprocessors. While, sure, there are plenty of other languages out there, and in this day and age, assembly is something of a line of last resort among “modern” computer programmers, on the Apple II, assembly remains the optimal way to build software for the best possible performance.

However, assembly language can be a little scary to newcomers, with a lot of seemingly cryptic stuff to look at and somewhat daunting code listings.

My intention with this series of articles is to introduce assembly language in a gentle, easy to manage way, taking very small steps. This will have two advantages:

  1. It should make it easier for you to follow and learn.
  2. It will reduce the size and complexity of articles, thereby hopefully letting me post more often. This will make Sean very happy.

The first thing you need to do is to select an assembler. There are a great many of them out there. The two best-known, and most highly-regarded, are arguably Merlin (which comes in both 8 and 16 bit versions) and ORCA/M (which also comes in both 8 and 16 bit versions).

Both of these options are good ones, and I can easily recommend them both. I do have some comments on them that you might want to consider while trying to decide between the two.

Merlin is easily the faster of the two assemblers. It also has a less steep learning curve, as its user interface is quite a lot simpler. That said, I find its editor to be rather quirky, with non-standard key equivalents for many things. In addition, source code files saved by Merlin have the high bits set on all the text, which means it’s not trivial to load the files in other editors, or to open them on other computers.

ORCA/M uses a Unix-like command line interface for everything. It has a significantly more powerful macro system, but that does have the drawback that the macros are rather harder to figure out how to create and use. Once you master it, however, ORCA/M’s power is formidable.

The Apple IIgs version of ORCA/M works within the ORCA shell environment, which lets you use multiple languages in one project. In ORCA, you can build your main code in, for example, C, then write key tidbits of your code in assembly to speed things up. This isn’t something you can do in Merlin.

All that said, choosing an assembler is a surprisingly personal decision. I like a great many things about both Merlin and ORCA, and use them both.

The primary drawback to Merlin is that its legal status is somewhat uncertain. The wife of its author, Glen Bredon, released it as freeware upon his death a few years back. However, it’s unclear whether or not she actually had the legal right to do so, since Roger Wagner Publishing owned the copyright to the software, and RWP has since been absorbed through multiple companies until ownership of the copyright is somewhat hard to determine.

If you can find a used copy of Merlin, you might find that you like it.

Both the 16-bit and 8-bit versions of ORCA/M, on the other hand, are still available for purchase (please note that I own the company that sells it; it’s only fair for me to mention that).

Because ORCA is still available in a clearly legal fashion, the code examples I’ll be providing will be using its syntax most of the time; however, I will strive to point out the differences as we go.

Next time, we’ll take a look at how to go about actually building code in these assemblers, so you’ll be ready to go when we start learning how to write assembly code.

December 19th, 2006

Syndicomm store reopens

Syndicomm reopened its online store this evening after being offline for most of a week for upgrades. The store has all products available for purchase, although there may be the occasional glitch. In particular, products that include links to other products in their descriptions probably will take you to the wrong page, and the site’s appearance hasn’t been customized yet.

December 10th, 2006

Syndicomm store being revamped

Syndicomm is in the process of moving its online store to a new software package that should help clear up some of the strange problems it’s been having. It’s currently offline, but will return shortly. It may take a couple of weeks after that to finish moving all the products back into the new store.

December 6th, 2006

Syndicomm to offer discs of GNO Apple II library in 2007

Starting early in 2007, Syndicomm will offer discs containing the contents of the GNO Apple II library. The discs will be sold for around US $5 apiece, and will be periodically updated to reflect the latest contents of the archive. A specific date on which the service will begin has not been determined yet.

November 30th, 2006

Juiced.GS 2007 renewals now available

Juiced.GS magazine renewals for the 2007 subscription year are now available for purchase for subscribers in both the United States and the rest of the world. Juiced.GS is the only remaining printed magazine for Apple II users and enthusiasts.

September 13th, 2006

Sweet16 1.7.3 released

Tonight, Eric Shepherd released Sweet16 1.7.3, which fixes speed control to work correctly on PowerPC, fixes the timing of certain interrupts (games that were playing at the wrong speed should work better now), and now supports the Dvorak and French Canadian keyboard layouts.

« Previous Page« Previous Entries | Next Entries »Next Page »