summaryrefslogtreecommitdiff
path: root/resources/Assembly In One Step.html
blob: 2a57ad164ebea3edfbce0e11e876009252340a30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Assembly In One Step</title>
<style id="abu-collapse-styles" type="text/css"></style></head>
<body text="#000000" bgcolor="#ffffff">
<!-- following code added by server. PLEASE REMOVE -->
<!-- preceding code added by server. PLEASE REMOVE -->
<h2>Assembly In One Step</h2>
<i>RTK, last update: 23-Jul-97</i><p>

A brief guide to programming the 6502 in assembly language.  It will 
introduce the 6502 architecture, addressing modes, and instruction set.
No prior assembly language programming is assumed, however it is assumed 
that you are somewhat familiar with hexadecimal numbers.  Programming
examples are given at the end.  Much of this material 
comes from <i>6502 Software Design</i> by Leo Scanlon, Blacksburg, 1980.
</p><p>

</p><hr>
<p></p><pre>
The 6502 Architecture
---------------------

   The 6502 is an 8-bit microprocessor that follows the memory oriented 
   design philosophy of the Motorola 6800.  Several engineers left 
   Motorola and formed MOS Technology which introduced the 6502 in 1975.  
   The 6502 gained in popularity because of it's low price and became the 
   heart of several early personal computers including the Apple II, 
   Commodore 64, and Atari 400 and 800.
   
   
   Simplicity is key
   -----------------
   
   The 6502 handles data in its registers, each of which holds one byte 
   (8-bits) of data.  There are a total of three general use and two special
   purpose registers:
   
   
      accumulator (A)  -  Handles all arithmetic and logic.  The real heart
                          of the system.
                          
      X and Y          -  General purpose registers with limited abilities.
      
      S                -  Stack pointer.
      
      P                -  Processor status.  Holds the result of tests 
                          and flags.
                          
                             
   Stack Pointer
   -------------
   
   When the microprocessor executes a JSR (Jump to SubRoutine) 
   instruction it needs to know where to return when finished.  The 6502 
   keeps this information in low memory from $0100 to $01FF and uses the 
   stack pointer as an offset.  The stack grows down from $01FF and makes 
   it possible to nest subroutines up to 128 levels deep.  Not a problem 
   in most cases.
   
   
   Processor Status
   ----------------
   
   The processor status register is not directly accessible by any 6502 
   instruction.  Instead, there exist numerous instructions that test the 
   bits of the processor status register.  The flags within the register 
   are:
   
   
       bit -&gt;   7                           0
              +---+---+---+---+---+---+---+---+
              | N | V |   | B | D | I | Z | C |  &lt;-- flag, 0/1 = reset/set
              +---+---+---+---+---+---+---+---+
              
              
       N  =  NEGATIVE. Set if bit 7 of the accumulator is set.
       
       V  =  OVERFLOW. Set if the addition of two like-signed numbers or the
             subtraction of two unlike-signed numbers produces a result
             greater than +127 or less than -128.
             
       B  =  BRK COMMAND. Set if an interrupt caused by a BRK, reset if
             caused by an external interrupt.
             
       D  =  DECIMAL MODE. Set if decimal mode active.
       
       I  =  IRQ DISABLE.  Set if maskable interrupts are disabled.
             
       Z  =  ZERO.  Set if the result of the last operation (load/inc/dec/
             add/sub) was zero.
             
       C  =  CARRY. Set if the add produced a carry, or if the subtraction
             produced a borrow.  Also holds bits after a logical shift.
             
             
   Accumulator
   -----------
   
   The majority of the 6502's business makes use of the accumulator.  All 
   addition and subtraction is done in the accumulator.  It also handles 
   the majority of the logical comparisons (is A &gt; B ?) and logical bit 
   shifts.
   
   
   X and Y
   -------
   
   These are index registers often used to hold offsets to memory 
   locations.  They can also be used for holding needed values.  Much of 
   their use lies in supporting some of the addressing modes.
   

   
Addressing Modes
----------------

   The 6502 has 13 addressing modes, or ways of accessing memory.  The 65C02 
   introduces two additional modes.
   
   They are:
   
   
      +---------------------+--------------------------+
      |      mode           |     assembler format     |
      +=====================+==========================+
      | Immediate           |          #aa             |
      | Absolute            |          aaaa            |
      | Zero Page           |          aa              |   Note:
      | Implied             |                          |
      | Indirect Absolute   |          (aaaa)          |     aa = 2 hex digits
      | Absolute Indexed,X  |          aaaa,X          |          as $FF
      | Absolute Indexed,Y  |          aaaa,Y          |
      | Zero Page Indexed,X |          aa,X            |     aaaa = 4 hex
      | Zero Page Indexed,Y |          aa,Y            |          digits as
      | Indexed Indirect    |          (aa,X)          |          $FFFF
      | Indirect Indexed    |          (aa),Y          |
      | Relative            |          aaaa            |     Can also be
      | Accumulator         |          A               |     assembler labels
      +---------------------+--------------------------+
      
      (Table 2-3. _6502 Software Design_, Scanlon, 1980)
      
   
   Immediate Addressing
   --------------------
   
   The value given is a number to be used immediately by the 
   instruction.  For example, LDA #$99 loads the value $99 into the 
   accumulator.
   
   
   Absolute Addressing
   -------------------
   
   The value given is the address (16-bits) of a memory location that 
   contains the 8-bit value to be used.  For example, STA $3E32 stores 
   the present value of the accumulator in memory location $3E32.
   
   
   Zero Page Addressing
   --------------------
   
   The first 256 memory locations ($0000-00FF) are called "zero page".  The 
   next 256 instructions ($0100-01FF) are page 1, etc.  Instructions 
   making use of the zero page save memory by not using an extra $00 to 
   indicate the high part of the address.  For example,
   
      LDA $0023   -- works but uses an extra byte
      LDA $23     -- the zero page address
      
      
   Implied Addressing
   ------------------
   
   Many instructions are only one byte in length and do not reference 
   memory.  These are said to be using implied addressing.  For example,
   
      CLC  -- Clear the carry flag
      DEX  -- Decrement the X register by one
      TYA  -- Transfer the Y register to the accumulator
      
      
   Indirect Absolute Addressing
   ----------------------------
   
   Only used by JMP (JuMP).  It takes the given address and uses it as a 
   pointer to the low part of a 16-bit address in memory, then jumps to 
   that address.  For example,
   
      JMP ($2345)   -- jump to the address in $2345 low and $2346 high
      
      So if $2345 contains $EA and $2346 contains $12 then the next 
      instruction executed is the one stored at $12EA.  Remember, the 
      6502 puts its addresses in low/high format.
   
   
   Absolute Indexed Addressing
   ---------------------------
   
   The final address is found by taking the given address as a base and 
   adding the current value of the X or Y register to it as an offset.  So,
   
      LDA $F453,X  where X contains 3
      
   Load the accumulator with the contents of address $F453 + 3 = $F456.
   
   
   Zero Page Indexed Addressing
   ----------------------------
   
   Same as Absolute Indexed but the given address is in the zero page 
   thereby saving a byte of memory.
   
   
   Indexed Indirect Addressing
   ---------------------------
   
   Find the 16-bit address starting at the given location plus the 
   current X register.  The value is the contents of that address.  For 
   example,
   
      LDA ($B4,X)  where X contains 6
      
   gives an address of $B4 + 6 = $BA.  If $BA and $BB contain $12 and 
   $EE respectively, then the final address is $EE12.  The value at 
   location $EE12 is put in the accumulator.
   
   
   Indirect Indexed Addressing
   ---------------------------
   
   Find the 16-bit address contained in the given location ( and the one 
   following).  Add to that address the contents of the Y register.  
   Fetch the value stored at that address.  For example,
   
      LDA ($B4),Y  where Y contains 6
      
   If $B4 contains $EE and $B5 contains $12 then the value at memory 
   location $12EE + Y (6) = $12F4 is fetched and put in the accumulator.
   
   
   Relative Addressing
   -------------------
   
   The 6502 branch instructions use relative addressing.  The next byte 
   is a signed offset from the current address, and the net sum is the 
   address of the next instruction executed.  For example,
   
      BNE $7F   (branch on zero flag reset)
      
   will add 127 to the current program counter (address to execute) and 
   start executing the instruction at that address.  SImilarly,
   
      BEQ $F9   (branch on zero flag set)
      
   will add a -7 to the current program counter and start execution at 
   the new program counter address.
   
   Remember, if one treats the highest bit (bit 7) of a byte as a sign (0 
   = positive, 1 = negative) then it is possible to have numbers in the 
   range -128 ($80) to +127 (7F).  So, if the high bit is set, i.e. the 
   number is &gt; $7F, it is a negative branch.  How far is the branch?  If 
   the value is &lt; $80 (positive) it is simply that many bytes.  If the 
   value is &gt; $7F (negative) then it is the 2's compliment of the given 
   value in the negative direction.
   
      2's compilment
      --------------
      
      The 2's compilment of a number is found by switching all the bits 
      from 0 -&gt; 1 and 1 -&gt; 0, then adding 1.  So,
      
      $FF  =  1111 1111   &lt;-- original
              0000 0000   &lt;-- 1's compliment
           +          1  
              ---------
              0000 0001   &lt;-- 2's compliment, therefore $FF = -1
              
      Note that QForth uses this for numbers greater than 32768 so that
      65535 = -1 and 32768 = -32768.
      
   In practice, the assembly language programmer uses a label and the 
   assembler takes care of the actual computation.  Note that branches 
   can only be to addresses within -128 to +127 bytes from the present 
   address.  The 6502 does not allow branches to an absolute address.
   
   
   Accumulator Addressing
   ----------------------
   
   Like implied addressing, the object of the instruction is the 
   accumulator and need not be specified.
   
   
   
The 6502 Instruction Set
------------------------

   There are 56 instructions in the 6502, and more in the 65C02.  Many 
   instructions make use of more than one addressing mode and each 
   instruction/addressing mode combination has a particular hexadecimal 
   opcode that specifies it exactly.  So,
   
      A9  =  LDA #$aa   Immediate addressing mode load of accumulator
      AD  =  LDA $aaaa  Absolute addressing mode load of accumulator
      etc.
   
   
   Some 6502 instructions make use of bitwise logic.  This includes AND, 
   OR, and EOR (Exclusive-OR).  The tables below illustrate the effects 
   of these operations:
   
      AND   1  1  -&gt;  1    "both"
            1  0  -&gt;  0
            0  1  -&gt;  0
            0  0  -&gt;  0
            
      OR    1  1  -&gt;  1    "either one or both"
            1  0  -&gt;  1
            0  1  -&gt;  1
            0  0  -&gt;  0
            
      EOR   1  1  -&gt;  0    "one or the other but not both"
            1  0  -&gt;  1
            0  1  -&gt;  1
            0  0  -&gt;  0
   
    Therefore,  $FF AND $0F  =  $0F since,
    
             1111 1111
        and  0000 1111
             ---------
             0000 1111  = $0F
   
   
   AND is useful for masking bits.  For example, to mask the high order 
   bits of a value AND with $0F:
   
      $36 AND $0F  =  $06
      
   OR is useful for setting a particular bit:
   
      $80 OR $08   =  $88
      
      since  1000 0000  ($80)
             0000 1000  ($08)
          or ---------
             1000 1000  ($88)
   
   EOR is useful for flipping bits:
   
      $AA EOR $FF  =  $55
      
      since  1010 1010  ($AA)
             1111 1111  ($FF)
         eor ---------
             0101 0101  ($55)
   
   
   Other 6502 instructions shift bits to the right or the left or rotate 
   them right or left.  Note that shifting to the left by one bit is the 
   same as multipling by 2 and that shifting right by one bit is the same 
   as dividing by 2.
   
   
   The 6502 instructions fall naturally into 10 groups with two odd-ball 
   instructions NOP and BRK:
   
      Load and Store Instructions
      Arithmetic Instructions
      Increment and Decrement Instructions
      Logical Instructions
      Jump, Branch, Compare and Test Bits Instructions
      Shift and Rotate Instructions
      Transfer Instructions
      Stack Instructions
      Subroutine Instructions
      Set/Reset Instructions
      NOP/BRK Instructions
      
      
   
   Load and Store Instructions
   ===========================
   
   LDA  - LoaD the Accumulator
   LDX  - LoaD the X register
   LDY  - LoaD the Y register
   
   STA  - STore the Accumulator
   STX  - STore the X register
   STY  - STore the Y register
   
   Microprocessors spend much of their time moving stuff around in 
   memory.  Data from one location is loaded into a register and stored 
   in another location, often with something added or subtracted in the 
   process.  Memory can be loaded directly into the A, X, and Y registers 
   but as usual, the accumulator has more addressing modes available.
   
   If the high bit (left most, bit 7) is set when loaded the N flag on 
   the processor status register is set.  If the loaded value is zero the 
   Z flag is set. 
   
   
   Arithmetic Instructions
   =======================
   
   ADC  - ADd to accumulator with Carry
   SBC  - SuBtract from accumulator with Carry
   
   The 6502 has two arithmetic modes, binary and decimal.  Both addition 
   and subtraction implement the carry flag to track carries and borrows 
   thereby making multibyte arithmetic simple.  Note that in the case of 
   subtraction it is necessary to SET the carry flag as it is the opposite 
   of the carry that is subtracted.
   
   Addition should follow this form:
   
   CLC
   ADC ...    
   .
   .
   ADC ...
   .
   .
   .
   
   Clear the carry flag, and perform all the additions.  The carry 
   between additions will be handled in the carry flag.  Add from low 
   byte to high byte.  Symbolically, the net effect of an ADC instruction is:
   
   A + M + C  --&gt;  A
   
   
   Subtraction follows the same format:
   
   SEC
   SBC ...
   .
   .
   SBC ...
   .
   .
   .
   
   In this case set the carry flag first and then do the subtractions.  
   Symbolically,
   
   A - M - ~C  --&gt;  A  ,  where ~C is the opposite of C
   
   
   Ex.1
   ----
        A 16-bit addition routine.  $20,$21 + $22,$23 = $24,$25
        
           CLC         clear the carry
           LDA $20     get the low byte of the first number
           ADC $22     add to it the low byte of the second
           STA $24     store in the low byte of the result
           LDA $21     get the high byte of the first number
           ADC $23     add to it the high byte of the second, plus carry
           STA $25     store in high byte of the result
           
           ... on exit the carry will be set if the result could not be
               contained in 16-bit number.
               
   Ex.2
   ----
        A 16-bit subtraction routine.  $20,$21 - $22,$23 = $24,$25
        
           SEC         clear the carry
           LDA $20     get the low byte of the first number
           SBC $22     add to it the low byte of the second
           STA $24     store in the low byte of the result
           LDA $21     get the high byte of the first number
           SBC $23     add to it the high byte of the second, plus carry
           STA $25     store in high byte of the result
           
           ... on exit the carry will be set if the result produced a 
               borrow
               
   Aside from the carry flag, arithmetic instructions also affect the N, 
   Z, and V flags as follows:
   
      Z = 1  if result was zero, 0 otherwise
      N = 1  if bit 7 of the result is 1, 0 otherwise
      V = 1  if bit 7 of the accumulator was changed, a sign change
      
      
   
   Increment and Decrement Instructions
   ====================================
   
   INC  - INCrement memory by one
   INX  - INcrement X by one
   INY  - INcrement Y by one

   DEC  - DECrement memory by one
   DEX  - DEcrement X by one
   DEY  - DEcrement Y by one

   The 6502 has instructions for incrementing/decrementing the index 
   registers and memory.  Note that it does not have instructions for 
   incrementing/decrementing the accumulator.  This oversight was 
   rectified in the 65C02 which added INA and DEA instructions.  The 
   index register instructions are implied mode for obvious reasons while 
   the INC and DEC instructions use a number of addressing modes.
   
   All inc/dec instructions have alter the processor status flags in the 
   following way:
   
     Z = 1  if the result is zero, 0 otherwise
     N = 1  if bit 7 is 1, 0 otherwise
     
   
   
   Logical Instructions
   ====================
   
   AND  - AND memory with accumulator
   ORA  - OR memory with Accumulator
   EOR  - Exclusive-OR memory with Accumulator
   
   These instructions perform a bitwise binary operation according to the 
   tables given above.  They set the Z flag if the net result is zero and 
   set the N flag if bit 7 of the result is set.
   
   
   
   Jump, Branch, Compare, and Test Bits
   ====================================
   
   JMP  - JuMP to another location (GOTO)
   
   BCC  - Branch on Carry Clear,       C = 0
   BCS  - Branch on Carry Set,         C = 1
   BEQ  - Branch on EQual to zero,     Z = 1
   BNE  - Branch on Not Equal to zero, Z = 0
   BMI  - Branch on MInus,             N = 1
   BPL  - Branch on PLus,              N = 0
   BVS  - Branch on oVerflow Set,      V = 1
   BVC  - Branch on oVerflow Clear,    V = 0
   
   CMP  - CoMPare memory and accumulator
   CPX  - ComPare memory and X
   CPY  - ComPare memory and Y
   
   BIT  - test BITs
   
   This large group includes all instructions that alter the flow of the 
   program or perform a comparison of values or bits.
   
   JMP simply sets the program counter (PC) to the address given.  
   Execution proceeds from the new address.  The branch instructions are 
   relative jumps.  They cause a branch to a new address that is either 
   127 bytes beyond the current PC or 128 bytes before the current PC.  
   Code that only uses branch instructions is relocatable and can be run 
   anywhere in memory.
   
   The three compare instructions are used to set processor status bits.  
   After the comparison one frequently branches to a new place in the 
   program based on the settings of the status register.  The 
   relationship between the compared values and the status bits is,
   
   
          +-------------------------+---------------------+
          |                         |  N       Z       C  |
          +-------------------------+---------------------+
          | A, X, or Y  &lt;  Memory   |  1       0       0  |
          | A, X, or Y  =  Memory   |  0       1       1  |
          | A, X, or Y  &gt;  Memory   |  0       0       1  |
          +-----------------------------------------------+
          
          
   The BIT instruction tests bits in memory with the accumulator but 
   changes neither.  Only processor status flags are set.  The contents 
   of the specified memory location are logically ANDed with the 
   accumulator, then the status bits are set such that,
   
   * N receives the initial, un-ANDed value of memory bit 7.
   * V receives the initial, un-ANDed value of memory bit 6.
   * Z is set if the result of the AND is zero, otherwise reset.
   
   So, if $23 contained $7F and the accumulator contained $80 a BIT $23 
   instruction would result in the V and Z flags being set and N reset since 
   bit 7 of $7F is 0, bit 6 of $7F is 1, and $7F AND $80 = 0.
   
   
   
   Shift and Rotate Instructions
   =============================
   
   ASL  - Accumulator Shift Left
   LSR  - Logical Shift Right
   ROL  - ROtate Left
   ROR  - ROtate Right
   
   Use these instructions to move things around in the accumulator or 
   memory.  The net effects are (where C is the carry flag):

   
           +-+-+-+-+-+-+-+-+ 
      C &lt;- |7|6|5|4|3|2|1|0| &lt;- 0    ASL
           +-+-+-+-+-+-+-+-+
           
           +-+-+-+-+-+-+-+-+ 
      0 -&gt; |7|6|5|4|3|2|1|0| -&gt; C    LSR
           +-+-+-+-+-+-+-+-+

           +-+-+-+-+-+-+-+-+ 
      C &lt;- |7|6|5|4|3|2|1|0| &lt;- C    ROL
           +-+-+-+-+-+-+-+-+

           +-+-+-+-+-+-+-+-+ 
      C -&gt; |7|6|5|4|3|2|1|0| -&gt; C    ROR
           +-+-+-+-+-+-+-+-+


    Z is set if the result it zero.  N is set if bit 7 is 1.  It is 
    always reset on LSR.  Remember that ASL A is equal to multiplying by 
    two and that LSR is equal to dividing by two.
    
    
    
    Transfer Instructions
    =====================
    
    TAX  - Transfer Accumulator to X
    TAY  - Transfer Accumulator to Y
    TXA  - Transfer X to accumulator
    TYA  - Transfer Y to Accumulator
    
    Transfer instructions move values between the 6502 registers.  The N 
    and Z flags are set if the value being moved warrants it, i.e.
    
    LDA #$80
    TAX
    
    causes the N flag to be set since bit 7 of the value moved is 1, while
    
    LDX #$00
    TXA
    
    causes the Z flag to be set since the value is zero.
    
    
    
    Stack Instructions
    ==================
    
    TSX  - Transfer Stack pointer to X
    TXS  - Transfer X to Stack pointer

    PHA  - PusH Accumulator on stack
    PHP  - PusH Processor status on stack
    PLA  - PulL Accumulator from stack
    PLP  - PulL Processor status from stack
    
    TSX and TXS make manipulating the stack possible.  The push and pull 
    instructions are useful for saving register values and status flags.  
    Their operation is straightforward.
    
    
    
    Subroutine Instructions
    =======================
    
    JSR  - Jump to SubRoutine
    RTS  - ReTurn from Subroutine
    RTI  - ReTurn from Interrupt
    
    Like JMP, JSR causes the program to start execution of the next 
    instruction at the given address.  Unlike JMP, JSR pushes the address 
    of the next instruction after itself on the stack.  When an RTS 
    instruction is executed the address pushed on the stack is pulled off 
    the stack and the program resumes at that address.  For example,
    
    LDA #$C1   ; load the character 'A'
    JSR print  ; print the character and it's hex code
    LDA #$C2   ; load 'B'
    JSR print  ; and print it
    .
    .
    .
 print JSR $FDED  ; print the letter
       JSR $FDDA  ; and its ASCII code
       RTS        ; return to the caller
    
    RTI is analagous to RTS and should be used to end an interrupt routine.
    
    
    
    Set and Reset (Clear) Instructions
    ==================================
    
    CLC  - CLear Carry flag
    CLD  - CLear Decimal mode
    CLI  - CLear Interrupt disable
    CLV  - CLear oVerflow flag
    
    SEC  - SEt Carry
    SED  - SEt Decimal mode
    SEI  - SEt Interrupt disable
    
    These are one byte instructions to specify processor status flag 
    settings.
    
    CLC and SEC are of particular use in addition and subtraction 
    respectively.  Before any addition (ADC) use CLC to clear the carry 
    or the result may be one greater than you expect.  For subtraction 
    (SBC) use SEC to ensure that the carry is set as its compliment is 
    subtracted from the answer.  In multi-byte additions or subtractions 
    only clear or set the carry flag before the initial operation.  For 
    example, to add one to a 16-bit number in $23 and $24 you would write:
    
    LDA $23     ; get the low byte
    CLC         ; clear the carry
    ADC #$02    ; add a constant 2, carry will be set if result &gt; 255
    STA $23     ; save the low byte
    LDA $24     ; get the high byte
    ADC #$00    ; add zero to add any carry that might have been set above
    STA $24     ; save the high byte
    RTS         ; if carry set now the result was &gt; 65535
    
    Similarly for subtraction,
    
    LDA $23     ; get the low byte
    SEC         ; set the carry
    SBC #$02    ; subtract 2
    STA $23     ; save the low byte
    LDA $24     ; get the high byte
    SBC #$00    ; subtract 0 and any borrow generated above
    STA $24     ; save the high byte
    RTS         ; if the carry is not set the result was &lt; 0
    
    
    
    Other Instructions
    ==================
    
    NOP  - No OPeration (or is it NO oPeration ? :)
    BRK  - BReaK
    
    NOP is just that, no operation.  Useful for deleting old 
    instructions, reserving room for future instructions or for use in 
    careful timing loops as it uses 2 microprocessor cycles.
    
    BRK causes a forced break to occur and the processor will immediately 
    start execution of the routine whose address is in $FFFE and $FFFF.  
    This address is often the start of a system monitor program.
    
    
    
Some simple programming examples
================================

    A few simple programming examples are given here.  They serve to 
    illustrate some techniques commonly used in assembly programming.  
    There are doubtless dozens more and I make no claim at being a 
    proficient assembly language programmer.  For examples of addition 
    and subtraction see above on CLC and SEC.
    
    
    A count down loop
    -----------------
    
            ; 
            ; An 8-bit count down loop
            ;
            
            start LDX #$FF    ; load X with $FF = 255
            loop  DEX         ; X = X - 1
                  BNE loop    ; if X not zero then goto loop
                  RTS         ; return
                  
            How does the BNE instruction know that X is zero?  It 
            doesn't, all it knows is that the Z flag is set or reset.  
            The DEX instruction will set the Z flag when X is zero.
                  
                  
            ;
            ; A 16-bit count down loop
            ;
            
            start LDY #$FF    ; load Y with $FF
            loop1 LDX #$FF    ; load X with $FF
            loop2 DEX         ; X = X - 1
                  BNE loop2   ; if X not zero goto loop2
                  DEY         ; Y = Y - 1
                  BNE loop1   ; if Y not zero goto loop1
                  RTS         ; return
                  
            There are two loops here, X will be set to 255 and count to 
            zero for each time Y is decremented.  The net result is to 
            count the 16-bit number Y (high) and X (low) down from $FFFF 
            = 65535 to zero.
            
            
    Other examples
    --------------
    
    ** Note: All of the following examples are lifted nearly verbatim from 
             the book "6502 Software Design", whose reference is above. 
             
             
           ; Example 4-2.  Deleting an entry from an unordered list
           ;
           ; Delete the contents of $2F from a list whose starting
           ; address is in $30 and $31.  The first byte of the list
           ; is its length.
           ;
           
           deluel  LDY #$00  	; fetch element count
                   LDA ($30),Y
                   TAX          ; transfer length to X
                   LDA $2F      ; item to delete
           nextel  INY          ; index to next element
                   CMP ($30),Y  ; do entry and element match?
                   BEQ delete   ; yes. delete element
                   DEX          ; no. decrement element count
                   BNE nextel   ; any more elements to compare?
                   RTS          ; no. element not in list. done
                   
           ; delete an element by moving the ones below it up one location
           
           delete  DEX          ; decrement element count
                   BEQ deccnt   ; end of list?
                   INY          ; no. move next element up
                   LDA ($30),Y
                   DEY
                   STA ($30),Y
                   INY
                   JMP delete
           deccnt  LDA ($30,X)  ; update element count of list
                   SBC #$01
                   STA ($30,X)
                   RTS
                   
                   
                   
           
           ; Example 5-6.  16-bit by 16-bit unsigned multiply
           ;
           ; Multiply $22 (low) and $23 (high) by $20 (low) and
           ; $21 (high) producing a 32-bit result in $24 (low) to $27 (high)
           ;
           
           mlt16   LDA #$00     ; clear p2 and p3 of product
                   STA $26
                   STA $27
                   LDX #$16     ; multiplier bit count = 16
           nxtbt   LSR $21      ; shift two-byte multiplier right
                   ROR $20
                   BCC align    ; multiplier = 1?
                   LDA $26      ; yes. fetch p2
                   CLC
                   ADC $22      ; and add m0 to it
                   STA $26      ; store new p2
                   LDA $27      ; fetch p3
                   ADC $23      ; and add m1 to it
           align   ROR A        ; rotate four-byte product right
                   STA $27      ; store new p3
                   ROR $26
                   ROR $25
                   ROR $24
                   DEX          ; decrement bit count
                   BNE nxtbt    ; loop until 16 bits are done
                   RTS
                   
                   
                   
           ; Example 5-14.  Simple 16-bit square root.
           ;
           ; Returns the 8-bit square root in $20 of the
           ; 16-bit number in $20 (low) and $21 (high). The
           ; remainder is in location $21.
           
           sqrt16  LDY #$01     ; lsby of first odd number = 1
                   STY $22
                   DEY
                   STY $23      ; msby of first odd number (sqrt = 0)
           again   SEC
                   LDA $20      ; save remainder in X register
                   TAX          ; subtract odd lo from integer lo
                   SBC $22
                   STA $20
                   LDA $21      ; subtract odd hi from integer hi
                   SBC $23
                   STA $21      ; is subtract result negative?
                   BCC nomore   ; no. increment square root
                   INY
                   LDA $22      ; calculate next odd number
                   ADC #$01
                   STA $22
                   BCC again
                   INC $23
                   JMP again
            nomore STY $20      ; all done, store square root
                   STX $21      ; and remainder
                   RTS
         
           
           This is based on the observation that the square root of an 
           integer is equal to the number of times an increasing odd 
           number can be subtracted from the original number and remain 
           positive.  For example,
           
                   25
                 -  1         1
                   --
                   24
                 -  3         2
                   --
                   21
                 -  5         3
                   --
                   16
                 -  7         4
                   --
                    9
                 -  9         5 = square root of 25
                   --
                    0


If you are truly interested in learning more, go to your public library 
and seek out an Apple machine language programming book.  If your public 
library is like mine, there will still be plenty of early 80s computer 
books on the shelves. :)
</pre>
<hr>
<img src="Assembly%20In%20One%20Step_files/index.html"><br>
Last update: 30-Jan-00<br>
<a href="https://dwheeler.com/6502/oneelkruns/65index.html"><b>Back</b></a>
<!-- text below generated by server. PLEASE REMOVE --><script language="JavaScript" src="http://us.i1.yimg.com/us.yimg.com/i/mc/mc.js"></script><script language="JavaScript" src="http://us.js2.yimg.com/us.js.yimg.com/lib/smb/js/hosting/cp/js_source/geov2_001.js"></script><script language="javascript">geovisit();</script><noscript><img src="http://visit.geocities.yahoo.com/visit.gif?us1247771236" alt="setstats" border="0" width="1" height="1"></noscript>
<img src="Assembly%20In%20One%20Step_files/serv.gif" alt="1" width="1" height="1">
</body></html>