Загрузка данных


; Laboratory 3, variant 24_26. Keil A51 / NXP 80C552.
; CW at X:7FFA = 000 i1 i0 j1 j0 op (i,j = 0..3).
; op=0: sort block IDs by descending count of linear zero runs.
; Equal counts keep increasing IDs. First ID occupies result bits 7..6.
; op=1: shift A, injecting one bit per step in the written order.
; Right input: B7,B6,B5,B3 (B3 is literal, NOT silently changed to B4).
;
; Program entry: 8000h. ULS INT0 entry: 8003h.

P4         EQU 0C0H
CONTROL    EQU 7FFAH
ARRAY_A    EQU 8000H
ARRAY_B    EQU 8004H

RESULT     DATA 30H
COMMAND    DATA 31H
INDEX_A    DATA 32H
INDEX_B    DATA 33H
OPERAND_A  DATA 34H
OPERAND_B  DATA 35H
SHIFT_N    DATA 36H
PRODUCT_LO DATA 37H
PRODUCT_HI DATA 38H
BLOCKS     EQU 40H             ; 40h..43h: blocks, low six bits
COUNTS     EQU 44H             ; 44h..47h: zero-run counts
IDS        EQU 48H             ; 48h..4Bh: sorted block IDs
TEMP_COUNT DATA 4CH
TEMP_ID    DATA 4DH
SHIFT_DIR  DATA 4EH            ; 0=left, 1=right

            ORG 8000H
            LJMP START
            ORG 8003H
            LJMP INT0_HANDLER
            ORG 8030H

START:
            MOV IE,#00H
            MOV SP,#5FH       ; stack 60h upward, outside banks/scratch
            MOV PSW,#00H      ; main program uses register bank 0
            MOV RESULT,#00H
            MOV P4,#00H
            ; A = [45h, A5h, 00h, A5h], B = [6Fh, 00h, 01h, 00h]
            MOV DPTR,#ARRAY_A
            MOV A,#045H
            MOVX @DPTR,A
            INC DPTR
            MOV A,#0A5H
            MOVX @DPTR,A
            INC DPTR
            CLR A
            MOVX @DPTR,A
            INC DPTR
            MOV A,#0A5H
            MOVX @DPTR,A
            INC DPTR
            MOV A,#06FH
            MOVX @DPTR,A
            INC DPTR
            CLR A
            MOVX @DPTR,A
            INC DPTR
            MOV A,#001H
            MOVX @DPTR,A
            INC DPTR
            CLR A
            MOVX @DPTR,A
            SETB P3.2         ; release INT0 input
            SETB IT0          ; falling edge, not low level
            CLR IE0
            SETB EX0
            SETB EA
MAIN_LOOP:
            MOV A,RESULT
DISPLAY_WRITE:
            MOV P4,A
            SJMP MAIN_LOOP

; Save all shared CPU context. Bank 1 is private to the ISR.
; RESULT is an intentional output: never restored from the stack.
INT0_HANDLER:
            PUSH ACC
            PUSH PSW
            PUSH B
            PUSH DPL
            PUSH DPH
            MOV PSW,#08H
            MOV DPTR,#CONTROL
            MOVX A,@DPTR
            ANL A,#01FH
            MOV COMMAND,A
            RR A
            RR A
            RR A
            ANL A,#03H
            MOV INDEX_A,A
            ADD A,#LOW ARRAY_A
            MOV DPL,A
            MOV DPH,#HIGH ARRAY_A
            MOVX A,@DPTR
            MOV OPERAND_A,A
            MOV A,COMMAND
            RR A
            ANL A,#03H
            MOV INDEX_B,A
            ADD A,#LOW ARRAY_B
            MOV DPL,A
            MOV DPH,#HIGH ARRAY_B
            MOVX A,@DPTR
            MOV OPERAND_B,A
            MOV A,COMMAND
            JB ACC.0,DO_OPERATION_2
            LCALL OPERATION_1
            SJMP STORE_RESULT
DO_OPERATION_2:
            LCALL OPERATION_2
STORE_RESULT:
            MOV RESULT,A      ; single publication of finished result
ISR_EXIT:
            POP DPH
            POP DPL
            POP B
            POP PSW
            POP ACC
            RETI

; Build 4 blocks using a ROM bit-position table. Table position 0 means
; A0, position 7 means A7, position 8 means B0, position 15 means B7.
OPERATION_1:
            MOV R0,#BLOCKS
            MOV R1,#COUNTS
            MOV R4,#00H       ; next table entry (0..23)
            MOV R7,#04H
BUILD_BLOCK:
            MOV R5,#00H
            MOV R6,#06H
BUILD_BIT:
            MOV DPTR,#BIT_POSITIONS
            MOV A,R4
            MOVC A,@A+DPTR
            INC R4
            LCALL READ_SOURCE_BIT ; returns source bit in C
            MOV A,R5
            RLC A
            MOV R5,A
            DJNZ R6,BUILD_BIT
            MOV @R0,A
            INC R0
            LCALL COUNT_ZERO_RUNS
            MOV @R1,A
            INC R1
            DJNZ R7,BUILD_BLOCK

            MOV IDS+0,#00H
            MOV IDS+1,#01H
            MOV IDS+2,#02H
            MOV IDS+3,#03H
            MOV R7,#03H       ; three bubble-sort passes
SORT_PASS:
            MOV R0,#COUNTS
            MOV R1,#IDS
            MOV A,R7
            MOV R6,A
SORT_PAIR:
            MOV A,@R0
            MOV TEMP_COUNT,A
            INC R0
            MOV A,@R0
            MOV R5,A
            CLR C
            SUBB A,TEMP_COUNT
            JC SORT_NEXT      ; right < left: keep
            JZ SORT_NEXT      ; equal: keep stable order
            MOV A,TEMP_COUNT
            MOV @R0,A
            DEC R0
            MOV A,R5
            MOV @R0,A
            INC R0
            MOV A,@R1
            MOV TEMP_ID,A
            INC R1
            MOV A,@R1
            DEC R1
            MOV @R1,A
            INC R1
            MOV A,TEMP_ID
            MOV @R1,A
            DEC R1
SORT_NEXT:
            INC R1
            DJNZ R6,SORT_PAIR
            DJNZ R7,SORT_PASS

            MOV R0,#IDS
            MOV R6,#04H
            CLR A
PACK_ID:
            RL A
            RL A
            ORL A,@R0
            INC R0
            DJNZ R6,PACK_ID
            RET

; Input A=bit position 0..15; preserve R0,R1,R4,R5,R6,R7.
READ_SOURCE_BIT:
            MOV R2,A
            ANL A,#07H
            MOV R3,A
            INC R3
            MOV A,R2
            ANL A,#08H
            JZ SOURCE_IS_A
            MOV A,OPERAND_B
            SJMP EXTRACT_BIT
SOURCE_IS_A:
            MOV A,OPERAND_A
EXTRACT_BIT:
            RRC A
            DJNZ R3,EXTRACT_BIT
            RET

; Input A=block in bits 5..0; output A=number of maximal linear zero
; runs. Inspect EXACTLY six bits; high padding bits must not count.
; Working R2=bits, R3=remaining, B=previous bit (initially 1).
COUNT_ZERO_RUNS:
            RL A
            RL A
            MOV R2,A
            MOV R3,#06H
            MOV B,#01H
            CLR A
            MOV R5,A
COUNT_NEXT:
            MOV A,R2
            JNB ACC.7,COUNT_ZERO
            MOV B,#01H
            SJMP COUNT_ADVANCE
COUNT_ZERO:
            MOV A,B
            JZ COUNT_ADVANCE
            INC R5
            MOV B,#00H
COUNT_ADVANCE:
            MOV A,R2
            RL A
            MOV R2,A
            DJNZ R3,COUNT_NEXT
            MOV A,R5
            RET

; Products are unsigned 16-bit. Compare HIGH bytes first, then LOW.
OPERATION_2:
            MOV A,INDEX_B
            ADD A,#02H
            MOV B,A
            MOV A,INDEX_A
            MUL AB
            MOV B,#05H
            DIV AB
            MOV SHIFT_N,B
            MOV SHIFT_DIR,#00H

            MOV A,INDEX_B
            INC A
            MOV B,A
            MOV A,OPERAND_A
            MUL AB
            MOV PRODUCT_LO,A
            MOV PRODUCT_HI,B
            MOV A,INDEX_A
            ADD A,#02H
            MOV B,A
            MOV A,OPERAND_B
            MUL AB
            MOV R2,A          ; right-hand product, low byte
            MOV R3,B          ; right-hand product, high byte
            MOV A,PRODUCT_HI
            CLR C
            SUBB A,R3
            JC SELECT_RIGHT
            JNZ SHIFT_PREPARE
            MOV A,PRODUCT_LO
            CLR C
            SUBB A,R2
            JNC SHIFT_PREPARE ; equality selects left
SELECT_RIGHT:
            MOV SHIFT_DIR,#01H
SHIFT_PREPARE:
            MOV A,SHIFT_N
            JZ NO_SHIFT
            MOV R7,A
            MOV A,OPERAND_A
            MOV R5,A
            MOV A,SHIFT_DIR
            JNZ SHIFT_RIGHT_PREP

            MOV A,OPERAND_B
            MOV R4,A
SHIFT_LEFT_LOOP:
            MOV A,R4
            CLR C
            RRC A             ; next B0,B1,B2,B3 into C
            MOV R4,A
            MOV A,R5
            RLC A
            MOV R5,A
            DJNZ R7,SHIFT_LEFT_LOOP
            RET

SHIFT_RIGHT_PREP:
            MOV R4,#00H
SHIFT_RIGHT_LOOP:
            MOV DPTR,#RIGHT_POSITIONS
            MOV A,R4
            MOVC A,@A+DPTR
            INC R4
            LCALL READ_SOURCE_BIT
            MOV A,R5
            RRC A
            MOV R5,A
            DJNZ R7,SHIFT_RIGHT_LOOP
            RET
NO_SHIFT:
            MOV A,OPERAND_A
            RET

BIT_POSITIONS:
            DB 7,15,5,13,3,11 ; block 00: A7 B7 A5 B5 A3 B3
            DB 6,14,4,12,2,10 ; block 01: A6 B6 A4 B4 A2 B2
            DB 3,11,1,9,7,15  ; block 10: A3 B3 A1 B1 A7 B7
            DB 2,10,0,8,6,14  ; block 11: A2 B2 A0 B0 A6 B6
RIGHT_POSITIONS:
            DB 15,14,13,11    ; B7 B6 B5 B3, literal task order
            END