2

我对组装还很陌生,我正在尝试打印出给定数字的素数分解。经过数小时的网上搜索,我发现了一些关于 DIV 指令的有用花絮,但我无法让我的代码做我想做的事。

我做了一些非常错误的事情,但我无法发现它。请哪位好心人帮我看一下?

.data
myMessage BYTE "Please enter a number to be evaluated:",0dh,0ah,0
factor DWORD 2
hold DWORD ?
.code
main PROC
    call Clrscr  

    mov  edx,offset myMessage
    call WriteString            ;Displays myMessage
    call ReadDec                ;Puts value into EAX register
    mov edi, factor
    call prime


    exit
main ENDP

prime PROC

step1:  xor edx, edx
        div edi
        cmp edx, 1
        jz step2
        add factor, 1
        mov edi, factor
        jmp step1

step2:  mov hold, eax
        mov eax, edi
        call WriteDec
        mov eax, hold
        CMP eax, 1
        jz step3
        jmp step1

step3:  
        exit
prime ENDP


END main
4

1 回答 1

1

如果我了解您要做什么,我认为您对如何工作cmpjz工作有误解。

cmp通过从目标(第一个)中减去源(第二个)操作数而不存储结果,并根据结果设置标志来工作。对于无符号数,相关标志是进位和零。如果源大于目标,则减法将从其最高位置借位,其结果是设置进位标志。如果源和目标相同,则结果为零,并设置零标志。如果源小于目标,则减法不会导致 0 或导致进位,因此两个标志都将为 0。

jz和其他条件跳转)根据标志的当前状态执行跳转。具体来说,jz如果设置了零标志,将执行跳转。由于cmp设置零标志以指示其操作数相等,因此跳转 if equal ( je) 指令实际上与跳转为零指令相同。进位跳转 ( jc) 和下方跳转 ( jb) 指令也是相同的,原因相同。

由于cmp设置标志以指示哪个操作数更大,因此jz指令可能会令人困惑。如果操作数相等,它将跳转,而不是如果其中一个为零。查看您的代码step1

div edi
cmp edx, 1
jz step2

我认为如果除法的余数为 0,则您要做的是跳转到step2,但由于cmp工作方式,如果余数为 1,您实际上会跳转到 step2。修复很简单:将 1 更改为 0。 (注意:我改成jzje因为它更好地解释了跳转的原因。正如我之前所说,它们完全相同。)

div edi
cmp edx, 0
je step2

此外,在找不到因素的情况下,您不会保留旧值。例如,如果输入值为 3,您的step1循环将像这样工作:

  1. 开始:eax=3,edi=2
  2. 除以。eax_ edi将商存储在 中eax,余数存储在 中edx
    • 现在,eax=3/2=1,edx=3%2=1
  3. edx0吗?如果是这样,打印edi并转到循环的开头。
    • 不是,所以继续。
  4. 加 1 到edi。现在是3。
  5. 使用新值eax=1 和edi=3 执行步骤 2。
    • 现在,eax=1/3=0,edx=1%3=1
  6. ...

请注意,即使您没有找到因子, 的值eax也发生了变化。您需要做的是在进行除法之前保存其值。您可以为此使用hold变量,这意味着只要您找到一个因素,它就已经更新。您所要做的就是在开始循环之前存储该值,并在每个循环开始时恢复它。

        mov hold, eax
step1:  mov eax, hold
        xor edx, edx
        ...
于 2011-10-25T20:52:25.793 回答