spo600:6502_math
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| spo600:6502_math [2024/09/12 19:01] – [Rotate Right/Left] chris | spo600:6502_math [2025/01/23 22:27] (current) – [Multiplication and Division] chris | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== | ====== | ||
| - | The 6502 processor is limited to very simple math operations, and various processor flags affect these operations. | + | The [[6502]] processor is limited to very simple math operations, and various |
| ==== Decimal Mode ==== | ==== Decimal Mode ==== | ||
| Line 9: | Line 9: | ||
| In binary mode, operations are performed on a single 8-bit value. Numbers may be treated as signed or unsigned (the math is the same). | In binary mode, operations are performed on a single 8-bit value. Numbers may be treated as signed or unsigned (the math is the same). | ||
| - | In decimal mode, the each byte is treated as two decimal digits - the lower 4 bits represent the lower digit, and the upper 4 bits represent the upper digit. Numbers are counted as positive, and values greater than 9 are invalid. | + | In decimal mode, the each byte is treated as two decimal digits - the lower 4 bits represent the lower digit, and the upper 4 bits represent the upper digit. Numbers are counted as positive, and digit values greater than 9 are invalid. |
| Decimal mode is selected by setting the D (Decimal) flag in the [[6502# | Decimal mode is selected by setting the D (Decimal) flag in the [[6502# | ||
| Line 87: | Line 87: | ||
| ==== Multiplication and Division | ==== Multiplication and Division | ||
| - | There are no multiplication or division instructions on the 6502; it is up to the programmer to provide the appropriate logic. | + | There are no multiplication or division instructions on the 6502; it is up to the programmer to provide the appropriate logic. Typical implementations use a combination of shifts and adds; for example, to multiply by 12, the original value shifted left three times (x8) can be added to the original value shifted left two times (x4). |
| + | Here is a simple example subroutine which multiplies two 8-bit values, producing a 16-bit product as the result (this code can be tested on the [[6502 Emulator]]): | ||
| + | |||
| + | < | ||
| + | ; | ||
| + | ; Example of 8-bit x 8-bit multiply with | ||
| + | ; 16-bit result on a 6502 | ||
| + | ; | ||
| + | ; This code uses shift-and-add | ||
| + | ; | ||
| + | ; Chris Tyler 2025-01-23 for the SPO600 course | ||
| + | ; | ||
| + | ; Copyright (C)2025 Seneca Polytechnic | ||
| + | ; Licensed under the terms of the GPLv2+ | ||
| + | ; See the file LICENSE for details | ||
| + | |||
| + | ; ######### MACRO DEFINITIONS | ||
| + | ; === ZERO-PAGE MEMORY LOCATIONS | ||
| + | |||
| + | ; INPUT PARAMETERS AND RESULT | ||
| + | define M1 | ||
| + | |||
| + | define M2 | ||
| + | |||
| + | define RESULT | ||
| + | define RESULT_L $12 | ||
| + | define RESULT_H $13 | ||
| + | |||
| + | ; TEMPORARY COPIES OF M1, M2 | ||
| + | define T1 | ||
| + | |||
| + | define T2 | ||
| + | define T2_L $21 | ||
| + | define T2_H $22 | ||
| + | |||
| + | ; ######### TEST CODE | ||
| + | |||
| + | ; NOTE: THE NEXT TWO OPERANDS ARE IN DECIMAL! | ||
| + | ; THIS IS DUE TO THE LACK OF $ | ||
| + | |||
| + | LDA #7 ; FIRST MULTIPLICAND | ||
| + | STA M1 | ||
| + | |||
| + | LDA #9 ; SECOND MULTIPLICAND | ||
| + | STA M2 | ||
| + | |||
| + | JSR MULTIPLY ; MULTIPLY THE VALUES | ||
| + | |||
| + | BRK ; SEE 16 BIT RESULT AT ' | ||
| + | |||
| + | ; ######### MULTIPLY SUBROUTINE | ||
| + | ; MULTIPLY THE CONTENTS OF M1 BY THE CONTENTS | ||
| + | ; OF M2 AND STORE THE RESULT IN ' | ||
| + | ; | ||
| + | ; Operation: | ||
| + | ; 0. Multiplicand M1 is copied to temporary | ||
| + | ; variable T1. Multiplicand M2 is copied to | ||
| + | ; the 16-bit temporary variable T2. The | ||
| + | ; RESULT is zeroed out. | ||
| + | ; 1. If either multiplicand is zero, the | ||
| + | ; product is zero, so the routine returns | ||
| + | ; immediately with RESULT=0. | ||
| + | ; 2. T1 is shifted right. If the bit shifted | ||
| + | ; out (formerly bit 0) is a ' | ||
| + | ; value of T2 is added to the RESULT. | ||
| + | ; 4. If T1 is zero after the shift, the | ||
| + | ; multiplication is complete and the routine | ||
| + | ; returns. | ||
| + | ; 5. T2 is rotated left (multiplied by 2). | ||
| + | ; 6. Processing continues at step 2. | ||
| + | |||
| + | MULTIPLY: | ||
| + | LDA #$00 ; ZERO OUT THE RESULT AND Tn_H | ||
| + | STA RESULT_L | ||
| + | STA RESULT_H | ||
| + | STA T2_H | ||
| + | |||
| + | LDA M1 ; COPY M1 TO T1 | ||
| + | BEQ MULT_DONE | ||
| + | STA T1 | ||
| + | |||
| + | LDA M2 ; COPY M2 TO T2 | ||
| + | BEQ MULT_DONE | ||
| + | STA T2_L | ||
| + | |||
| + | JMP MULT_FIRST | ||
| + | |||
| + | MULT_NEXT: | ||
| + | ASL T2_L ; SHIFT T2 LEFT | ||
| + | ROL T2_H | ||
| + | |||
| + | MULT_FIRST: | ||
| + | LSR T1 ; SHIFT T1 RIGHT | ||
| + | BEQ MULT_LAST | ||
| + | BCC MULT_NEXT | ||
| + | |||
| + | LDA T2_L ; IF BIT0 WAS 1: | ||
| + | CLC ; T2 + RESULT-> RESULT | ||
| + | ADC RESULT_L | ||
| + | STA RESULT_L | ||
| + | LDA T2_H | ||
| + | ADC RESULT_H | ||
| + | STA RESULT_H | ||
| + | JMP MULT_NEXT | ||
| + | |||
| + | MULT_LAST: | ||
| + | LDA T2_L ; PRECEEDING BLOCK, BUT | ||
| + | CLC ; WE'VE AVOIDED A SECOND | ||
| + | ADC RESULT_L | ||
| + | STA RESULT_L | ||
| + | LDA T2_H ; PER LOOP ITERATION OR | ||
| + | ADC RESULT_H | ||
| + | STA RESULT_H | ||
| + | |||
| + | MULT_DONE: | ||
| + | RTS | ||
| + | </ | ||
| + | |||
| + | This code is available in the [[spo600: | ||
spo600/6502_math.1726167689.txt.gz · Last modified: 2024/09/12 19:01 by chris
