装配模数 x86

Modulus in Assembly x86

我的教授给我布置了一个作业,将此 C 代码转换为汇编代码

int k = 0, S = 0;
for (k=0; k<100; k++)
{
if (k%2 == 0)
S += k;
else
S -= k;
}

汇编只是我课程的一小部分,所以我们没有涉及很多技术部分。我唯一的问题是模数部分,我们只学过除法,从来没有学会如何使用模数。 这就是我的工作

MOV CX, 0; counter
MOV AX, 0; This represents S, we haven't learned how to declare variables in assembly, so we use registers instead)
Loop1: 
      CMP [Haven't done the modulus condition]
      JE iftrue
      JNE ifwrong
iftrue:
      ADD AX, CX
      INC CX
      CMP CX, 99
      JL Loop1
ifwrong:
      SUB AX, CX
      INC CX
      CMP CX, 99
      JL Loop1

你能帮我填写第一个条件吗?你如何在比较中使用模数并检查余数是否为0?

P.S.: 我也没有学会如何在循环中做条件,所以 iftrue/ifwrong 部分只是我这边的快速即兴创作,我不知道它是否有效或不。那部分可以用更好的形式完成吗?

教授通常不会布置涉及您尚未学过的东西的作业。对于外部观察者(例如阅读此问题的任何人),大多数可能是您没有注意,或者您没有意识到所解释的是实现模运算的一种方法。

x86汇编中的模数可以通过两个数相除得到。你把被除数放在某个寄存器中,你执行一些提供除数的指令,在指令执行后某个寄存器接收商,另一个寄存器接收余数。但这无关紧要,因为你可能还没有学会除法运算,没关系,因为我们不会使用除法

在 x86 汇编(以及任何其他汇编)中,您可以很容易地计算除法的余数 乘以 2 的幂,而无需使用除法运算. And 2 is a power of 2. (The 1st power of 2.)

实际上,对于 2 的情况,事情变得更加简单,因为我希望你同意,除以 2 的余数只有两种可能的结果是不言而喻的:1 或 0。

您可能还记得,二进制数字看起来像这样: 0011101010 最左边的位是最高有效位,最右边的位是最低有效位。表示数字的二进制系统的基本 属性 数字的最低有效位始终表示将该数字除以 2 后得到的余数。 (就像在十进制系统中一样,最右边的数字代表该数字除以 10 后的余数。)

因此,您需要做的就是从数字中分离出最低有效位。这将是 0 或 1,它将代表数字除以 2 的余数。

"Precisely how to achieve this is left as an exercise to the student."

(试一试,如果你做不到,post 另一个 Whosebug 问题。)

关于JE/JNE部分,实际上是错误的,因为当CX不再小于99时,JL Loop1指令将落入ifwrong:标签,这不是你想要什么。您应该按如下方式重写它:

    JE iftrue
ifwrong: ;unnecessary label, for illustration purposes only
    SUB AX, CX
    JMP after
iftrue:
    ADD AX, CX
    JMP after ;unnecessary instruction, for illustration purposes only.
after:
    INC CX
    CMP CX, 99
    JL Loop1

请注意,您并不完全需要 ADD AX, CXSUB AX, CX,您需要 ADD AX, MMSUB AX, MM,其中 MM 是 CX 模数 2,并且您仍在弄清楚如何计算。

另请注意,我不保证 CMP CX, 99 后跟 JL Loop1 是否正确,你没有问过,以后你可能会遇到,但应该很容易搞清楚。

test cx,1 根据 CX 的最后一位设置零标志。在这种情况下,等于或 JZ 对应于 cx % 2 == 0。使用 x-1 进行掩码是取模的一种特殊情况,仅适用于 x 是 2 的幂时。