America Online APPLE II DEVELOPMENT FORUM CONFERENCE LOG Tuesday, August 4, 1992 10:00 p.m. Eastern Time Topic: Assembly Language Programming Forum Leader: Gary Jacobson (AFL GaryJ) AFL GaryJ Welcome to the Apple II Development Forum! Tonight, our topic is... AFL GaryJ Tonight our topic is.... AFL GaryJ Assembly Language Programming! AFL GaryJ That is, 6502, 65816 assembly. AFL GaryJ Does anyone have any specific on-topic questions they'd like to start off with AFL GaryJ this evening? AFL Marty Yes AFL Marty Give me a couple of seconds though AFL GaryJ Does anyone here use any assembler other than ORCA/M on a regular AFL GaryJ basis? AFL Marty What is a bank relative program and why would someone need or want to AFL Marty make one? AFL GaryJ Bank relative... Where are you getting this term? AFL Marty Discussion of the Link command with the +B flag. AFL GaryJ That's what I was trying to understand where you are coming from. AFC DYAJim I assume you're referring to the "b" flag you can pass to the orca linker.. AFC DYAJim Normally when you create a program, the linker has to generate what we call a AFC DYAJim "relocation dictionary" full of information that is used to load the code in AFC DYAJim ANY memory address... AFC DYAJim Here is an example.. AFC DYAJim 0000: lda $0008 AFC DYAJim 0003: rts AFC DYAJim ... AFC DYAJim 0008: 00 00 (ds 2) AFC DYAJim now, this program tries to load a variable stored at offset 8 into it. AFC DYAJim so it does this by hardcoding the address as $0008. AFC DYAJim But what happens if you load this program into memory starting at say, $2000? AFC DYAJim Then it's variable will really be located at $2008, but encoded in the program AFC DYAJim it is loading its variable from $0008. So the relocation dictionary tells AFC DYAJim GS/OS that at offset 1 into the program (the operand of the lda $0008 - 08 00) AFC DYAJim to fill in the address the program was loaded into, plus eight. AFC DYAJim When you link a program the linker generates a whole huge bunch of these AFC DYAJim relocation statements, assuring that the program can be loaded and run from AFC DYAJim everywhere. AFC SteveB (Basically, you'll always want to keep your program relocatable... AFC SteveB Like any good SYS16 should be.) AFC DYAJim Now, after a while the list can get quite large... In most cases, this is AFC DYAJim fine - because as Steve says, you really should allow your program to be loaded AFL Marty Right. AFC DYAJim and run from anywhere.. AFC DYAJim What the "+b" flag does is constrict your program to loading at the beginning AFC DYAJim of a bank.. ($xx0000) AFC DYAJim This often severely limits where your program can be loaded, especially on AFC DYAJim low memory systems, so normally you don't want to mess with it.. The advantage AFC DYAJim is that when we assume that the program will always be loaded starting at $0000 AFC DYAJim of any bank, most of the information in the relocation dictionary becomes AFC DYAJim unnecessary, so the dictionary is smaller, so your file is smaller. AFC DYAJim But you lose ultimately, IMO, because now your program is much more restrictive AFC DYAJim on system resources. ga AFL Marty That's it? That's the only reason you'd want a program restricted that way? AFC DYAJim Yep, to save disk space by creating a smaller relocation dictionary.. Eric Greg Having that restriction can also cause all your purgeable blocks to be purged. Eric Greg This is usually bad. AFL GaryJ There might be a reason that code should start at a bank boundry, but AFL GaryJ I can't think of one :) AFL Marty Then I can't see why anyone would risk using it. I should think one would look AFL Marty for inefficiencies in the code before resorting to something that AFL Marty drastic. Jim Murphy One fine example of a program that uses bank-relative segments (or at least 1) is the 6.0 Finder. Jim Murphy Since its main segment is just about 64K, this was a fine candidate for bank-rel. AFL GaryJ But, the size of the segment would naturally restrict it to a bank that AFL GaryJ could accomodate it. I still don't see why it would be necessary for it AFL GaryJ (the Finder) to be bank relative. Jim Murphy Because it loads much faster. AFL GaryJ Ah, yes. If it's gonna be that big anyway, might as well make it more AFL GaryJ efficient. Eric Greg Because the Finder is already a huge file that has problems fitting on 3.5". Jim Murphy The loader has to do much less work since there really isn't much for it to do to patch that... Jim Murphy particular segment. AFL Marty Are there other examples outside of Finder? Jim Murphy Andy did quite a few interesting things to get the Finder to load faster - you should be happy. :-) AFL GaryJ That would be the reason for it. Something like the Finder is loaded very AFL GaryJ frequently, of course. AFL GaryJ Back in the old days when people used to write non-relocatable code, it might AFL GaryJ be a reason to fix a piece of code at a bank boundry. (With fixed AFA Jay org $2000 :) AFL GaryJ JSR's, and such). But that is totally inefficient today. AFL GaryJ Right, Jay :) AFL GaryJ I wonder if the IIGS AOL software is bank relative. (I'll have to check :) AFC SteveB Nope. AFC SteveB :) AFA Jay :) AFL Marty Thanks for the tutorial. I'm done. Next questioner. AFL GaryJ (Good question, Marty. Thanks) AFL GaryJ Anyone else with a question tonight? AFL GaryJ On really large programs for general applications, you'd probably want AFL GaryJ to make them into multiple segments, instead of a large main segment, like AFL GaryJ the Finder has. That way there'd be a greater chance of finding free AFL GaryJ memory. AFL GaryJ The Finder has an advantage, in that it is generally the first "application" to AFL GaryJ get loaded. AFC SteveB (Segment Foo can be in bank $10, segment Foo2 can be in $0E, etc.. :) AFL Marty So the Finder is, in a sense, a special case? AFL GaryJ Right. But in assembly, you have to program smarter in order to AFL GaryJ utilize multiple code segments. AFL GaryJ Well, I don't know if you'd call it a special case. I guess it just depends on AFL GaryJ what you really want to do. Minimize load time or accomodate people AFL GaryJ with low memory situations. AFL Marty I see. AFL GaryJ In assembly, if you create a multi segment program, you have to make sure you AFL GaryJ don't trip yourself up with the data bank register, and you also need to remember to AFL GaryJ do JSL's and RTL's to routines which are in different segments. AFA Jay ? A strange question AFL GaryJ GA, Jay AFA Jay I was just wondering if anyone knew or has thought about this... AFA Jay what is the fastest way to match two strings in assembly... AFA Jay just CMPing them... AFA Jay or what about SBCing? AFL GaryJ I've used both ways. It's basically the same thing. Are you comparing AFL GaryJ single bytes, or complete strings? AFA Jay complete strings. Eric Greg (EOR'ing them can test for equality... but it isn't any faster/slower...) AFA Jay I'm using SBCs now, it's pretty fast... AFA Jay I was just wondering if anyone ever cared to think about it :) AFL GaryJ The difference, of course, is that the contents of the accumulator is altered AFL GaryJ with a SBC. Eric Greg One good way involves a tight loop to check for the first character, then Eric Greg another loop to check the rest of the string (when searching a table of strings) AFA Jay Just looking at the two codes, CMP and SBC, they have the same cycle times... AFA Jay but what goes along with each of those might be slower. AFA Jay You see, I spent 2 hours trying to decide... AFA Jay I'd do it one way, compile it and try it, then the other way and I kept AFA Jay going back and forth trying to decide which was faster :) AFA Jay I bet they were equal :) Jim Murphy They most likely were. :-) AFL GaryJ I think the cycles are the same, but it depends on how you've designed your code. AFC SteveB Cycle counting time :) AFA Jay Well, the SBC felt faster :) Eric Greg Cycle times are listed on page 217 of the Hardware Ref. DangardAce Bob Sander-Cederlof used to use speaker tickling to see if a routine was DangardAce faster or not :) AFA Jay I've got cycle times everywhere, I just don't want to count :) Eric Greg I know the feeling. - Eric :) AFL GaryJ You don't have to count. AFL GaryJ Let ORCA do it for you. Eric Greg What! A ML programmer not counting cycles?!? Heresy! -Greg :) AFA Jay where's this flag that I've never found? :) AFL GaryJ (But you still have to follow the code, to determine if a branch is taken, etc.) DangardAce He reportedly just listened to the speaker tones.. higher tones meant the DangardAce routine was faster AFL GaryJ I'm trying to remember it... AFL GaryJ Just a sec.. AFL GaryJ I've used it a bunch of times, but it slips my mind at the moment.. Eric Greg If the routine is identical except for SBC or CMP, then there is no time diff.. AFL Marty Couldn't you use a stopwatch and run the code segment 1000 times? Eric Greg (unless you're doing an explicit SEC before your SBC, in which case that method Eric Greg is slower... -Greg AFA Jay Right, I was thinking things that go along with it... AFA Jay I seem to think there's MORE I do with the CMP... Eric Greg Jay: it's in the assembler; there's a flag or directive for it. - Eric AFA Jay since I also do case checking (upper vs. lower) AFL GaryJ Hmmm.... Eric Greg (Internally, SBC and CMP do the same thing, except the CMP doesn't save the AFL Marty It's an assembler directive... Eric Greg result... and doesn't need c=1 beforehand...) AFL Marty INSTIME AFL GaryJ Did you have a question, Jim? AFC DYAJim just about ready.. AFL Marty Must be one hell of a question. AFC DYAJim Alright.. first let me give some foreground info.. Greg Eric Foreground... uh, white? (Background=Med. Blue) :) AFC DYAJim This code is the code that detects if a key has been pressed (for Twilight).. AFC DYAJim It is called every vbl, so that it won't miss a keypress.. AFC DYAJim All it has to do is, if it detects a key has been pressed, increment AFC DYAJim kbdChangedFlg... It will never zero this flag.. AFC DYAJim Then another interrupt called every 30th of a second will read this flag and AFC DYAJim set it back to zero.. So basically if any key has been pressed in the last AFC DYAJim (up above, every 30th of a second should be twice every second) AFC DYAJim half a second, this variable should be TRUE. But I'm having a HELL of a time AFC DYAJim dealing with the keyboard strobe.. Modifiers work great, but I still miss AFC DYAJim many non-modifer keys with this routine.. AFC DYAJim shortm AFC DYAJim lda KEYMODREG AFC DYAJim and #%11011011 ; OA, opt, shift, ctrl, repeat, keypad AFC DYAJim beq noModifiers AFC DYAJim inc KbdChangedFlg AFC DYAJim bra abort AFC DYAJim AFC DYAJim noModifiers anop AFC DYAJim * if key pressed, and if different than last time then inc AFC DYAJim lda KBD AFC DYAJim sta NewKey AFC DYAJim bmi changed AFC DYAJim cmp OldKey AFC DYAJim beq nochange AFC DYAJim AFC DYAJim changed inc KbdChangedFlg AFC DYAJim nochange anop AFC DYAJim lda NewKey AFC DYAJim sta OldKey AFC DYAJim longm AFC DYAJim For some reason, it misses many normal keypresses.. (modifiers always work) Greg Eric Is this in Event Mgr. or non-? AFC DYAJim I can't use the event manager. Greg Eric No, we mean, are you losing keys under Event Mgr or non-Event Mgr apps? AFC DYAJim Oh... like under gno.. Greg Eric Do you mean GNO is a place you have this problem? Are there others? AFA Jay you're supposed to lose keypresses under GNO, it's the law. ;) Greg Eric GNO grabs keys in several different ways... it's likely you'll miss 'em. - Eric AFC DYAJim Yeah.. Well, I thought it was more widespread, but come to think of it I AFC DYAJim can't remember any more specific cases! (oops on my part) I'll do some more AFC DYAJim extensive testing tonight.. AFC DYAJim (So the routine looks good to you? :) Matt DTS "cmp OldKey" is unnecessary -- Apple never guarantees the old key stays at $C000 once you Matt DTS clear the keyboard strobe. It usually does, but why risk it? AFC DYAJim So you think I should just check bit 7 only? Matt DTS (Or do we guarantee that? Don't feel like looking it up) Anyway, it's unnecessary. AFC DYAJim (I never clear the strobe in twilight, but I think I see what you're saying) Greg Eric No, when the keyboard strobe gets cleared, the old key goes away... but it is Greg Eric reflected at the keyboard strobe location... not sure if it's documented that Greg Eric way...) -Greg AFL GaryJ What if the person presses the same key each time? AFC DYAJim That's usually a problem.. runs of keys Greg Eric Doesn't matter. The flag gets incremented once, it should trigger properly. - Eric AFC DYAJim So basically all I should be checking (for normal keys) is bit 7 of KBD? Matt DTS For normal keys. Your routine might or might not work under the Event Manager, like they said. Greg Eric Or bits 0-6 of $C010, I believe... -Greg AFC DYAJim But won't reading $c010 to get bits 0-6 reset the strobe? Greg Eric (or maybe that's only while it's down... argghhh) AFC DYAJim Under the Evt Mgr, should I use a keyboard interrupt? AFC DYAJim (because I can't exactly go calling GetNextEvent from a heartbeat :) Matt DTS Under the Event Manager, the _Event Manager_ has a keyboard interrupt handler, which is how it finds Matt DTS key-down events. You could call EventAvail, couldn't you? AFC DYAJim I know phantasm uses its own keyboard interrupt handler :) AFC DYAJim I'll try EventAvail. James S WI And it dosn't work. (Phantasm) Greg Eric I've got code to know when Events show up under the Event Manager... it patches Greg Eric _PostEvent... -Greg AFL GaryJ EventAvail should work, I would think. AFL GaryJ Thanks for the question, Jim. AFC DYAJim Sure, no problem! This code has been giving me headaches for days.. AFL GaryJ Anyone else have a question or comment? AFC DYAJim And since tonight just happened to be ASM night, I thought hey, why not :) Greg Eric Yeah, sure, Jim... take a walk on the wild side! :) - Eric Greg Eric How about the Fahr Side? -Greg AFC DYAJim Thought I'd run this by with everyone too.. AFC DYAJim Now, since I WANT to support both CloseView and allow modules to use shadowing AFC DYAJim for fast animation, is the only safe way to do this is save both 012000 and AFC DYAJim e12000 (checking 012000-01a000 first though to make sure that it was just a AFC DYAJim continuous handle so it couldn't contain code) then turning on shadowing and AFC DYAJim then calling the module? AFC DYAJim (I should note that this would be from ANY desktop program) AFL GaryJ The ONLY safe way? AFL GaryJ Is this for Twilight? Matt DTS (If you're waiting for me to pronounce something "safe" or "suppported", don't hold your breath.) AFC DYAJim Of course.. AFC DYAJim I'm not, I'm just asking if there's a better way which I haven't thought of. AFL GaryJ I can't think of any better ways... Matt DTS If you're going to allow shadowing, you _must_ save both screens because there's no guarantee both Matt DTS screens were identical before you turned on shadowing. AFC DYAJim Yeah.. that's what I thought.. thanks for the reassurance