assembly 无法从x86中的arr数字创建数字

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

所以我在汇编中有这个“计算器”,我有一个数组num 1db 4dup(0),用于4个数字,假设你输入9875,所以9在num 1的位置0,8的位置1,等等……num1 = [9,8,7,6]
我还有:
bdec dw 1000d、100d、10d、1d ; 10的幂与数位
int count = 0 ;我将对结果求和
我用这段代码在一个基于幂位置的数组中创建一个数字。
我希望代码能做到这一点:num1h = 9x10^3 + 8x10^2 + 7x10^1 + 5x10^0

NUM1P proc
        push ax
        push bx
        push cx
        
        mov di,0
        mov cx, 0
        mov ax, 0
        mov num1h,0
    
    power_base:
        mov al, [num1+di] 
        mov bx, [bdec+di]
        mul bx
        add num1h,ax
        inc cx
        inc di
        cmp cx,4
        je exitn1p
        jmp power_base

    exitn1p:

    pop cx
    pop bx
    pop ax

    ret
    endp

当我打印结果时,它返回25852
Result
现在打印功能工作正常,因为它打印BX中的任何内容,所以当我将一个数字直接移动到BX并使用打印功能时,比如说5637,它将工作正常:

call NUM1P
    ;mov bx, num1h
        mov bx, 5637 
    call IMPRIME_BX
    jmp jmp_mouse_no_clic

Correct result
但是当我尝试使用num 1h将一个号码直接传输到bx时,事情变得很奇怪...
有什么想法我可能做错了什么吗?
或者我如何调试一个有这样一个接口的程序?

oxosxuxt

oxosxuxt1#

一些bug

  • 虽然第一次执行mov al, [num1+di]时AH=0,但在接下来的迭代中不再是这种情况!你需要在循环中调零。
  • bdec 数组的类型为word,因此您需要以2字节为步长遍历该数组。使用这个inc di,您的代码当前仅以1个字节的步长遍历这个数组。

因为乘法可以直接使用内存操作数,所以获得正确结果的简单方法是:

mov al, [num1+di]   ; Step of 1 byte
  cbw
  mov bx, di
  mul [bdec+di+bx]    ; Step of 2 bytes

部分改进

  • 您将保留AX、BX和CX寄存器。同时,你不保留DI,但你知道DX寄存器被字长乘法修改了吗?
  • 你应该使用相反的条件跳转,这样你就有更少的分支要做,这通常是更快的。

类似于以下的构造:

cmp  cx, 4
  je   exitn1p
  jmp  power_base
exitn1p:

最好变成:

cmp  cx, 4
  jne  power_base
  • 您不需要单独的循环控制变量CX,因为DI包含相同的值,并且可以轻松地扮演该角色。
  • 您可以将mov num1h, 0替换为短2个字节的mov num1h, di,因为已知DI寄存器包含0。
  • 您可以将mov di, 0替换为短1个字节的xor di, di,该xor di, di同样会将DI寄存器置零。

新增代码

push ax
  push bx
  push dx
  push di
  xor  di, di
  mov  num1h, di       
power_base:
  mov  al, [num1+di]   ; -> AL=[0,9]
  cbw                  ; -> AX=[0,9]
  mov  bx, di
  mul  [bdec+di+bx]    ; Step of 2 bytes since DI is equal to BX
  add  num1h, ax
  inc  di
  cmp  di, 4
  jne  power_base
  pop  di
  pop  dx
  pop  bx
  pop  ax
  ret

相关问题