【问题标题】:div operation wraps over (x86 assembly)div 操作结束(x86 程序集)
【发布时间】:2015-09-27 06:48:55
【问题描述】:

我在 Visual Studio 2010 的 x86 程序集 (MASM) 中调用了一个过程。 它所做的只是获取存储在 ax 寄存器中的以 10 为基数的数字并将其转换为二进制字符串(例如 10100b)。我遇到的问题是,每当 ax 假设等于 1 时,它反而会换行并等于某个大数字。

.code
main proc

   xor eax, eax
   xor ebx, ebx
   xor ecx, ecx
   xor edx, edx

   lea esi, binResult                           ; convert result to string (binary notation)
   mov ax, [result]
   mov bx, 2
   call Convert2Bin


   lea esi, binResult                           ; test
   call PrintString



   EndofProgram:

   invoke ExitProcess, 0            
main endp


Convert2Bin proc                       ; Define procedure
        pushad                     ; save registers
        pushfd                     ; save flags

        divide_Convert2Bin:

        cmp eax, 1
        je addOne_ThenExit

        cmp eax, 0
        je addZero_ThenExit

        div ebx

        cmp edx, 1
        je addOne_ThenLoop

        cmp edx, 0
        je addZero_ThenLoop

        addOne_ThenLoop:
        mov byte ptr [esi], '1'
        inc esi
        jmp divide_Convert2Bin

        addZero_ThenLoop:
        mov byte ptr [esi], '0'
        inc esi
        jmp divide_Convert2Bin

        addOne_ThenExit:
        mov byte ptr [esi], '1'
        inc esi
        jmp done_Convert2Bin

        addZero_ThenExit:
        mov byte ptr [esi], '0'
        inc esi
        jmp done_Convert2Bin

        done_Convert2Bin:
        mov byte ptr [esi], 'b'

        popfd                      ; restore flags
        popad                      ; restore registers
        ret                        ; return to caller

【问题讨论】:

  • pusha/popa and` 和 pushf/popf 都相当慢。在 asm 中编写时,您可以在每个函数的基础上构建自己的 ABI,但是保存/恢复 everything 是一个糟糕的选择。标准 ABI 不保留标志,并且有一些调用者保存的寄存器,可以在函数中使用而无需保存。您只需要保存/恢复 ABI 指定为被调用者保存的寄存器。

标签: assembly x86 masm


【解决方案1】:

div ebx 需要在EAXEBXEDX 中输入某些值,并更改EAXEDX。至少你忘记了EDX的初始化:

...
pushfd                     ; save flags

mov ebx, 2                 ; Divisor

divide_Convert2Bin:

cmp eax, 1
je addOne_ThenExit

cmp eax, 0
je addZero_ThenExit

xor edx, edx                ; Don't forget to initialize EDX
div ebx
...

考虑一下,您以 reverse 顺序获得结果(余数)!

【讨论】:

  • @lasec0203:你必须在div之前每次都重复EDX的初始化,因为div改变了EDX
  • 我在调试器中检查了 EDX。每次都会被新的余数覆盖。它似乎没有导致 EAX 换行的问题。
  • @lasec0203: WTF ;-) 像我一样做,看看结果!
  • @lasec0203: div 计算 EDX:EAX / src -> EAX(余数在 EDX 中)。检查说明手册。 stackoverflow.com/tags/x86/info
  • @lasec0203:你有一个循环。第一个循环计算 EDX:EAX/BX -> EAX,余数 EDX。在div 之前需要EDX,在div 之后更改。在第二个循环中div 得到一个错误的EDX,EDX:EAX 现在是一个相当大的数字。您只想使用EAX,因此您可以取消错误的EDX (xor edx,edx)。当您编写汇编程序时,您必须始终检查寄存器是否仍然保持正确的值。
猜你喜欢
  • 2023-03-14
  • 2023-02-24
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2012-11-05
  • 2011-01-08
  • 1970-01-01
相关资源
最近更新 更多