assembly 8086程序集-一个简单的递归(数字前缀)回调问题

nr7wwzry  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(117)

你好,大会社区!目前我是一名工程专业的学生,我试着解决了一些我的家庭作业问题,其中大部分都很简单,但有一个问题困扰了我10个小时。
这个问题要求我创建一个例程,它接收十六进制格式的16位无符号数字使用堆栈并以十进制格式打印数字,以便每行代表每个前缀,例如对于输入'B26 Eh',我们应该得到:

  • 45678
  • 4567
  • 456
  • 45
  • 4

程序必须实现递归,我们必须通过堆栈提供输入。
我写了下面的代码:

.model small
.data
.stack 100h
.code
START:

    ; Setting screen data into ES register
    MOV AX, 0B800h 
    MOV ES, AX   
    
    ; Setting the data segment
    MOV AX, @data   
    MOV DS, AX
    
    ; Screen offset
    MOV CX, 0d 
    MOV BX, 340h
    
    ; Testing result
    MOV AX, 746FH
    PUSH AX
    CALL numPrefix
    
    
    ; Exit and print both runs
    MOV AX, 4C00h
    INT 21h
    
numPrefix PROC
    
    ; Save registers
    PUSH BP
    PUSH DX
    
    MOV BP, SP
    MOV AX, [BP+6d]
    
    ; Base condition
    CMP AX, 0
    JE baseCase
    
    ; Else, divide the input by 16d to get the quotient and remainder
    PUSH CX ; Save print address 
    mov cx, 10  ; Divisor
    xor dx, dx  ; Clear dx for the quotient
    div cx      ; Divide ax by cx, quotient in ax, remainder in dx
    POP CX
    
    ; Call numPrefix recursively with the quotient
    push ax     ; Push the quotient onto the stack
    call numPrefix
    
    
; PRINT LOGIC #################################################################################
    ; Now we print what we got for each row in the recursion
    MOV DH, 2Eh
    
    SUB BX, 0A0h
    PUSH BX
    PUSH CX
    
    CMP CX, 0d
    JE equalZero
    
    printLoop:
    ; For each row in the recursion, print the appropriate row of numbers
    MOV SI, BX
    MOV DI, [BX+0A0h]
    PUSH AX
    MOV AX, ES:[SI]
    MOV ES:[DI], AX
    POP AX
    
    ADD BX, 1
    loop printLoop
    
    equalZero:
    POP CX
    ; Add new member
    ADD BX, 1
    MOV ES:[BX], DX
    POP BX
    INC CX
    
; PRINT LOGIC #################################################################################
    ; Finish and restore registers
    
    ; Also Base case where we only print and not do recursion again
    baseCase:
    pop DX
    pop BP
    ret 2
    
numPrefix ENDP
END START

在我的脑海中的逻辑是相当简单的,我将使用的事实,除以16 h将给予我新的AX(商)和余数(DX)是要打印的。每次我递归地尝试重新调用这个例程,并为递归的每一级使用'print'函数,我复制前一行并将新的余数(DX)添加到新行。
代码不工作,我试着用DOSBOX调试了几个小时,每次我都认为我弄明白了,但最终调试器只是在我回调递归后跳到内存中的随机位置。我已经调试了几个小时了,希望能得到一些帮助。
谢谢你!
编辑:看来我修复了一些问题,我认为递归可以追溯到它的正常位置,但我似乎无法找回DX(余数),因为我从我的递归中追溯,感谢帮助!
最后一个问题:解决了,谢谢大家!

jv2fixgn

jv2fixgn1#

显然我写答案的时候你已经解决了。真有你的!所以它不会浪费,这是我想到的。可能有助于比较解决方案...
你的递归是好的,但与屏幕的交互不是。
例如,MOV DI, [BX+0A0h]必须是lea DI, [bx - 160]

ORG  256

  mov  ax, 0B800h 
  mov  es, ax   
  xor  cx, cx
  mov  bx, 0340h
  mov  ax, 746Fh
  push ax
  call numPrefix
  mov  ax, 4C00h
  int  21h
; ---------------------------
numPrefix:
  push bp
  push dx
  mov  bp, sp
  mov  ax, [bp+6]
  test ax, ax
  jz   baseCase

  mov  di, 10
  xor  dx, dx
  div  di
  push ax
  call numPrefix
  sub  bx, 160         ; 1 row up !!!
  push bx
  test cx, cx
  jz   equalZero
    
  push ax
  push cx
printLoop:
  mov  ax, [es:BX+160] ; copy from lower to higher !!!
  mov  [es:BX], ax
  add  bx, 2           ; 2 bytes per charactercell !!!
  loop printLoop
  pop  cx
  pop  ax

equalZero:
  add  dx, 2E30h       ; Convert to text plus set attribute !!!
  mov  [es:bx], dx
  pop  bx
  inc  cx
    
baseCase:
  pop  dx
  pop  bp
  ret  2

相关问题