【问题标题】:Add two 32-bit numbers using 8-bit registers使用 8 位寄存器将两个 32 位数字相加
【发布时间】:2021-04-05 09:32:52
【问题描述】:

这里的目标是两个以小端表示法存储的 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)

【问题讨论】:

  • 是的,绝对可以使用循环,并且应该使用它来完成。查看您的代码,哪些指令相似或相等,并查看指令集哪些指令可能有用。
  • @thebusybee 你能说得更具体点吗?如何使用 8 位寄存器引用 2 字节内存地址?
  • 一个接一个......或者如果你的意思是如何访问DPTRDPHDPL 有两半
  • @thebusybee 嗯,不知道你的意思。为了使用循环,我必须将内存地址存储在寄存器中以提取单个字节、递增它们等,但我不能在 8 位寄存器(R0、R1…)中存储像 0x3000 这样的 2 字节内存地址。跨度>
  • 好吧,再次请阅读文档。 DPTR 是一个 16 位寄存器。

标签: assembly 8051 8-bit


【解决方案1】:

知道外部存储器地址的低字节相同(00h),可以简化代码。这意味着我们可以在循环的整个迭代过程中保持数据指针 DPTR(特殊功能寄存器DPL 地址为 82h)的低字节不变。
要在 3 个外部 dword 之间切换,我们只需更改 DPTR 的高字节(特殊功能寄存器 DPH 地址为 83h)。

为了移动到所有涉及的双字中的下一个更高字节,我在循环底部使用了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

【讨论】:

    猜你喜欢
    • 2014-11-18
    • 2020-11-21
    • 1970-01-01
    • 2011-01-14
    • 2014-11-05
    • 2013-11-25
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多