使用 8 位寄存器将两个 32 位数字相加
Add two 32-bit numbers using 8-bit registers
这里的目标是将两个以小端表示法存储的 32 位数字相加。这些数字存储在以下存储单元中:
- 第一个数字:0x3000-0x3003
- 秒数:0x4000-0x4003
- 结果应为:0x5000-0x5003
以下是我的实现,从DRY原则来看效率不是很高:
ARG1 EQU 3000H
ARG2 EQU 4000H
RESULT EQU 5000H
ORG 0000H
MOV DPTR, #ARG1 + 0
MOV A, #12H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 1
MOV A, #34H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 2
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 3
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 0
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 1
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 2
MOV A, #56H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 3
MOV A, #78H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 0
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 0
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 0
MOVX @DPTR, A
MOV DPTR, #ARG1 + 1
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 1
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 1
MOVX @DPTR, A
MOV DPTR, #ARG1 + 2
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 2
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 2
MOVX @DPTR, A
MOV DPTR, #ARG1 + 3
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 3
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 3
MOVX @DPTR, A
JNC EXIT
INC A
MOVX @DPTR, A
EXIT:
NOP
SJMP $
END
问题:请问有没有什么方法可以使用循环实现,减少重复指令?
例如,此示例在直接寻址模式下使用 8 位内存地址时使用寄存器组:
ORG 0H
MOV 30H, #12H
MOV 31H, #34H
MOV 32H, #00H
MOV 33H, #00H
MOV 40H, #00H
MOV 41H, #00H
MOV 42H, #56H
MOV 43H, #78H
MOV R0, #30H ;pointer of bank 0
MOV R1, #50H ;result storage bank 0
MOV R2, #4 ;counter
SETB RS0
MOV R1, #40H ;pointer bank 1
CLR RS0
CLR C
LOOP:
MOV A, @R0
SETB RS0
ADDC A, @R1
INC R1
CLR RS0
MOV @R1, A
INC R0
INC R1
DJNZ R2, LOOP
JNC EXIT
INC @R1
EXIT:
NOP
SJMP $
END
(我正在使用 µVision IDE)
知道外存地址低字节相同(00h),可以简化代码。这意味着我们可以在整个循环迭代中保持数据指针 DPTR(特殊功能寄存器 DPL
地址 82h)的低字节固定。
要在 3 个外部双字之间切换,我们只需更改 DPTR(地址 83h 处的特殊功能寄存器 DPH
)的高字节。
为了移动到所有涉及的双字中的下一个更高字节,我在循环底部使用了 INC 82h
指令。使用 INC
(而不是 ADD
)很重要,因为 INC
不会更改我们希望通过循环传播的进位标志 C。
MOV 82h, #00h ; DPL = 00h
MOV R1, #4 ; Each dword has 4 bytes
CLR C ; Clear carry so 1st ADDC works fine
LOOP:
MOV 83h, #30h ; DPH = 30h --> DPTR == [3000h,3003h]
MOVX A, @DPTR ; Load byte from 1st dword
MOV R0, A ; Free the accumulator (MOVX needs A)
MOV 83h, #40h ; DPH = 40h --> DPTR == [4000h,4003h]
MOVX A, @DPTR ; Load byte from 2nd dword
ADDC A, R0 ; Addition defines carry
MOV 83h, #50h ; DPH = 50h --> DPTR == [5000h,5003h]
MOVX @DPTR, A ; Store byte in 3rd dword
INC 82h ; DPL++
DJNZ R1, LOOP ; Decrement counter and loop back if not zero
; Process the final carry as needed
这里的目标是将两个以小端表示法存储的 32 位数字相加。这些数字存储在以下存储单元中:
- 第一个数字:0x3000-0x3003
- 秒数:0x4000-0x4003
- 结果应为:0x5000-0x5003
以下是我的实现,从DRY原则来看效率不是很高:
ARG1 EQU 3000H
ARG2 EQU 4000H
RESULT EQU 5000H
ORG 0000H
MOV DPTR, #ARG1 + 0
MOV A, #12H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 1
MOV A, #34H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 2
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 3
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 0
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 1
MOV A, #00H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 2
MOV A, #56H
MOVX @DPTR, A
MOV DPTR, #ARG2 + 3
MOV A, #78H
MOVX @DPTR, A
MOV DPTR, #ARG1 + 0
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 0
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 0
MOVX @DPTR, A
MOV DPTR, #ARG1 + 1
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 1
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 1
MOVX @DPTR, A
MOV DPTR, #ARG1 + 2
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 2
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 2
MOVX @DPTR, A
MOV DPTR, #ARG1 + 3
MOVX A, @DPTR
MOV R0, A
MOV DPTR, #ARG2 + 3
MOVX A, @DPTR
ADDC A, R0
MOV DPTR, #RESULT + 3
MOVX @DPTR, A
JNC EXIT
INC A
MOVX @DPTR, A
EXIT:
NOP
SJMP $
END
问题:请问有没有什么方法可以使用循环实现,减少重复指令?
例如,此示例在直接寻址模式下使用 8 位内存地址时使用寄存器组:
ORG 0H
MOV 30H, #12H
MOV 31H, #34H
MOV 32H, #00H
MOV 33H, #00H
MOV 40H, #00H
MOV 41H, #00H
MOV 42H, #56H
MOV 43H, #78H
MOV R0, #30H ;pointer of bank 0
MOV R1, #50H ;result storage bank 0
MOV R2, #4 ;counter
SETB RS0
MOV R1, #40H ;pointer bank 1
CLR RS0
CLR C
LOOP:
MOV A, @R0
SETB RS0
ADDC A, @R1
INC R1
CLR RS0
MOV @R1, A
INC R0
INC R1
DJNZ R2, LOOP
JNC EXIT
INC @R1
EXIT:
NOP
SJMP $
END
(我正在使用 µVision IDE)
知道外存地址低字节相同(00h),可以简化代码。这意味着我们可以在整个循环迭代中保持数据指针 DPTR(特殊功能寄存器 DPL
地址 82h)的低字节固定。
要在 3 个外部双字之间切换,我们只需更改 DPTR(地址 83h 处的特殊功能寄存器 DPH
)的高字节。
为了移动到所有涉及的双字中的下一个更高字节,我在循环底部使用了 INC 82h
指令。使用 INC
(而不是 ADD
)很重要,因为 INC
不会更改我们希望通过循环传播的进位标志 C。
MOV 82h, #00h ; DPL = 00h
MOV R1, #4 ; Each dword has 4 bytes
CLR C ; Clear carry so 1st ADDC works fine
LOOP:
MOV 83h, #30h ; DPH = 30h --> DPTR == [3000h,3003h]
MOVX A, @DPTR ; Load byte from 1st dword
MOV R0, A ; Free the accumulator (MOVX needs A)
MOV 83h, #40h ; DPH = 40h --> DPTR == [4000h,4003h]
MOVX A, @DPTR ; Load byte from 2nd dword
ADDC A, R0 ; Addition defines carry
MOV 83h, #50h ; DPH = 50h --> DPTR == [5000h,5003h]
MOVX @DPTR, A ; Store byte in 3rd dword
INC 82h ; DPL++
DJNZ R1, LOOP ; Decrement counter and loop back if not zero
; Process the final carry as needed