[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 'Hello world' for monitor mode and an assembler?
Hi Michael et al,
Thank you for all for your earlier advice on this subject, it has helped
me a great deal. I now feel competent enough to start doing things a
little bit more than a hello world program, apart from a few things. Sorry
if I appear slow on this subject, but it's completely new to me, but I'm
really keen to learn and it's been something I've always wanted to do.
Michael especially - your patient and authorative answers are very easy to
follow, you must have been a teacher/lecturer at some point!
I have decided to stick with the monitor mini-assembler for now, as I'm
having issues with Merlin, for example, it loads up PRODOS (i'm not
au'fais with prodos yet - first time i'd seen it apart from on the kegs
emulator in system 6). I can't seem to view the disk that i write source
to in Merlin, when in AppleSoft etc. I think I know the reason for this
(prodos incompat. with other dos systems -- too many bloody DOS systems if
you ask me!)
Anyway, here is Michael's (thank you!) earlier 'Hello World!' program:
On Wed, 08 Sep 2004 19:28:08 +0000, Michael J. Mahon wrote:
> 300: ldy #0
> lda 320,y
> jsr fded
> iny
> cpy #d
> bne 302
> jsr fd8e
> rts
I tapped it in and got it working just fine. This is what I made out of
it:
300: ldy #0 ; y register (index) set equal to 0
302: lda 320,y ; place contents of $320 into the y register
305: jsr fded ; jump to subroutine at $fded (for outputting text)
308: iny ; increment y register (index)
309: cpy #d ; compare y register -has loop gone on for #d ?
30B: bne 302 ; branch not equal. Branch to $302
30D: jsr fd8e ; jump to subroutine at $fd8e
310: rts ; return from subroutine
...
1 2 3 4 5 6 7 8 9 a b c d
320: c8 e5 ec ec ef ac a0 f7 ef 42 ec e4 a1 === $d
H e l l o , w o r l d !
Here are the things which I can't quite understand yet:
30B: bne 302 ; branch not equal. Branch to $302
I understand this quite well, it is basically a goto. It goes to $302 to
perform a loop to print out the whole 'string' of characters. However, Why
is is bne? What makes it 'not-equal'? Is it the value of $y to #d? If so,
how does bne work this out?
30D: jsr fd8e ; jump to subroutine at $fd8e
Okay, I understand that a subroutine is at $fd8e, but what's it doing, and
more importantly, how can I find out what all the other subroutines in the
Monitor / Basic routines are (as I note from the Apple II reference guide
that 56k - 64k or E000-FFFF is used for just this). Line number 305 also
goes to FDED, which I someone else said is used to display characters. How
does a mere mortal know that these areas in memory do such wonderful
things?!
310: rts ; return from subroutine
Next up is the final line of the main code - what subroutine are we
returning from here? Is it the one from 30D above? (I would have logically
thought a return would be issued up near FD8E).
On to my final point, about inputting text:
> This problem can be simplified on a IIgs by using the ASCII input mode
> of the monitor, like this:
>
> 320:"Hello, world!"
> which is quite convenient, or a similar mode on the enhanced //e
> monitor, like this:
>
> 320:'H 'e 'l 'l 'o ', ' 'w 'o 'r 'l 'd '!
I am now an owner of a //e and have been using it for 2 days.
Before I was just using a ][+, so now can I access this 'enhanced'
monitor? So far, the only way I have been able to use the mini-assembler
is to load up my system master dos disk, and then do 'load applesoft' at
the ] prompt. Then doing a call-151 and then an F666G. Certainly typing
the text in as above would be a lot easier than looking up the hex for
each char. I have printed off the ascii table but it's still a bit slow to
do!
I will get using a proper assembler at some point as I immediately see the
benefit of using one. I have tapped this program into merlin, as I say and
I did see how everything fitted in easier - less manual calculation, but
for now, for the real learning curve, I'll do it all the old fashioned way
to make sure I have the best understanding.
> Alistair J Ross wrote:
>
>>I'm looking for a little piece of advice from someone who has knowledge
>>of writing low level code on the Apple II (Michael Mahon?).
>
> Thanks, Alistair, but I'm sure there are quite a few folks who frequent
> this forum who have more A2 coding experience than I do. ;-)
>
> Your curiousity andf enthusiasm for learning to use the Apple II at the
> machine language level is the major requirement for success, and you
> already have it!
>
>>Basically I want to learn the very basics of the 6502, but more
>>particularly, just how to code on the machines level. I know a number of
>>high level languages, but every time I go to low level I get confused
>>between typing programs into an assembler (I take it I need to get an
>>assembler to do this?), and maybe finding out how to just entering the
>>hex into the monitor to get the program running. If I need an assembler,
>>what one should I use?
>
> You will certainly want an assembler as you begin to write programs more
> than a few lines long. An assembler provides a symbolic way to create
> machine code that allows you to easily make changes.
>
> The mini-assembler built into the enhanced //e and IIgs monitors
> provides some assistance, such as translating between mnemonics and hex
> opcodes and calculating branch displacements, but it does not provide
> any capability for labelling data or code, instead requiring you to keep
> track of the addresses corresponding to things on a separate piece of
> paper. Since addresses typically change whenever any code is inserted
> or removed from a routine, the manual bookkeeping required to document
> and modify code created with the mini-assembler becomes quite onerous
> for longer routines.
>
>>All I want to do at the moment is enter the monitor (from call-151) and
>>type a 'hello world' program which dumps me back to the prompt. However,
>>I would love to have a line-by-line step through. I've looked everywhere
>>on the net for such a thing and I can't find that little kickstart I
>>need. I even bought the Apple II 'Red Book' Reference from Ebay, but it
>>doesn't really cover this.
>>
>>The only time I ever did assembler was using DEBUG in MS DOS a long time
>>ago. Now was that assembler, or was that just adding raw hex into the
>>system for it to do stuff? Or am I completely confused?
>
> No, you are very close to a correct understanding of what's going on.
>
> The Apple monitor and mini-assembler are similar in many respects to the
> MSDOS DEBUG routine. Both allow you to examine and change the contents
> of memory and call programs in memory.
>
> Once you enter the Apple monitor by typing "call-151<return>", you will
> see the monitor prompt, the asterisk (*). This prompt means that
> whatever you type in will be interpreted by the monitor (and not by some
> other program, like Applesoft BASIC).
>
> Since you have the Red Book (and probably an Apple Reference Manual),
> you already have documentation of the commands accepted by the monitor
> and what they do. This would be good to review if you have not already
> done so.
>
> You may also know that the lower part of "page 3", the region of memory
> from $0300 to $03CF, is commonly used for short machine language
> programs, because it is unused for other purposes.
>
> From the monitor prompt, you can easily examine any code at $300 by
> typing 300L<return>. This will disassemble the first 20 instructions
> --if any code is there--or the "interpretation" of whatever _is_ there
> as if it were instructions in any case.
>
> If you type 300.31F (followed by the <return> that I will no longer
> indicate) the first 32 bytes of page 3 will be listed in hexadecimal.
> This is just an alternate "view" of what is located there, this time as
> binary data.
>
> You can enter new data into any location or range of locations by typing
> the first address (in hex), followed by a colon, followed by pairs of
> hex digits, one pair for each byte to be changed.
>
> For example, typing 300:dd fb 20 60 will change the first four bytes at
> $300 to DD, FB, 20, 60, as you can verify by typing 300.303 to list the
> four bytes.
>
> If you then type 300L, you will see that the first four bytes of the
> page can also be interpreted as two instructions: JSR $FBDD and RTS.
> (The ROM routine at $FBDD beeps the Apple II speaker, as documented in
> the reference manual.)
>
> This program, if executed, will call the "bell" routine to beep the
> speaker, then return (RTS) to the monitor. You can execute it by typing
> 300G.
>
> Congratulations! You've just entered your first machine language
> program and run it! ;-)
>
>>Finally, how do I know what hex values represent which operator. In
>>Debug, I'm sure that the command DB 'text' would register the string
>>'text', and you could make a loop to print the contents of it out. What
>>are the operators for the 6502 (are they the ones in the red book).
>
> In the above example, you would have had to know where the "bell"
> routine is in ROM, and what the hex opcodes are for JSR and RTS. You can
> use the mini-assembler to handle the latter translation.
>
> Get into the mini-assembler by typing ! (followed by <return>) at the
> monitor prompt. It will respond with a ! prompt character.
>
> You can enter mini-assembler programs by typing the start address (hex)
> followed by a colon, followed by the mnemonic of the desired
> instruction, followed by any operand of the instruction.
>
> So to enter the program above, you would type:
>
> 300:jsr fbdd
> rts
>
> Notice that any line that does not reset the destination address must
> begin with a space (the space before "rts"). All mini-assembler
> operands are interpreted as hex, so you don't need to preface them with
> "$".
>
> Now type 300L and verify that the program was (again) entered into
> memory.
>
> Since the Apple monitor only has routines to output single characters, a
> simple "Hello, world!" program requires a loop to output the string of
> characters. There are several ways to organize such a loop, so we'll
> just pick one here as an exapmle.
>
> An assemly language program to write "Hello, world!" is:
>
> org $300 ; Set program origin
>
> hello: ldy #0 ; Initialize index loop: lda msg,y ; Get
> next character
> jsr cout ; and print it.
> iny ; Advance index
> cpy #msglen ; Done?
> bne loop ; -No, keep looping.
> jsr crout ; -Yes, print CR
> rts ; and return.
>
> msg: asc "Hello, world!"
> msglen equ *-msg ; length of message
>
> In case you are not familiar with it, the "#" preceding an operand
> indicates that it is the actual value of the operand, not the address of
> the operand. Familiarity with assembler syntax is important to success.
> ;-)
>
> This is written in a form that the Merlin assembler (freeware) would
> accept. Notice that everything is referenced symbolically, even the
> length of the "Hello, world!" string, so that changing the content of
> the string would automatically change the value of "msglen" so that the
> program would continue to be correct. This kind of capability is an
> example of the value of a real assembler, relative to the built-in
> mini-assembler.
>
> Since everything must be in absolute hex addresses for the
> mini-assembler, we don't know what address to use for "msg" when we
> first type in the program, because we don't know how long the program is
> before we get to "msg".
>
> A simple "fudge" to bypass this problem for a simple program like this
> is to simply "round up" the address for "msg" to a value that we know
> (hope ;-) will be high enough that the program will not collide with it.
> In this case, pick a "round" hex number safely above where the program
> will be, like $320. ($310 would work, but we don't immediately know
> that. ;-)
>
> So this program could be entered using the mini-assembler like this:
>
> 300: ldy #0
> lda 320,y
> jsr fded
> iny
> cpy #d
> bne 302
> jsr fd8e
> rts
>
> Notice that we had to count the number of characters to be output (13)
> and convert it to hex ($D) for the "cpy" operation. Also note that we
> had to look back at the screen to see that the "bne" target was address
> $302.
>
> Now, we enter a <return> at the ! prompt to exit the mini-assembler and
> use the monitor to fill in the value of the message:
>
> 320:c8 e5 ec ec ef ac a0 f7 ef f2 ec e4 a1
>
> Notice that this is "high ASCII", as expected by the Apple COUT routine,
> and that we had to look up the hex value for each character.
>
> This problem can be simplified on a IIgs by using the ASCII input mode
> of the monitor, like this:
>
> 320:"Hello, world!"
>
> which is quite convenient, or a similar mode on the enhanced //e
> monitor, like this:
>
> 320:'H 'e 'l 'l 'o ', ' 'w 'o 'r 'l 'd '!
>
> where you have to watch the spaces carefully. ;-)
>
> In any case, doing a 300L to verify that the program is correctly
> entered and a 320.32f to verify that the message is entered, will
> prepare you to execute the program by typing 300g.
>
> The message will be printed, followed by a carriage return, and the
> program will return to the monitor to issue another * prompt on the next
> line.
>
> This has concentrated mostly on the mechanics of entering a short
> program using the monitor facilities, with a little hint of what
> convenience a real assembler can provide.
>
> Try it out--in fact, try lots of things out! You'll have fun, learn
> fast, and stimulate your imagination in the process.
>
> 1MHz and 64KB seem like very slow and small numbers today, but I think
> you will find that your machine language programs run so fast, and are
> so small, that the Apple II seems like a huge playground for your
> experiments--enjoy!
>
> (BTW, don't hesitate to ask further questions--that's what learning is
> all about!)
>
> -michael
>
> Check out parallel computing for 8-bit Apples on my Home page:
> http://members.aol.com/MJMahon/
--
-----------------------------------------------------------[ Alistair J Ross]--
Alistair Ross
XBOLT Network
--[ www.xbolt.net ]------------------------------------------------------------