Assembly 组件x86中的模数

Assembly 组件x86中的模数,assembly,x86,modulus,Assembly,X86,Modulus,我的教授给了我一个任务,要我把这个C代码转换成汇编代码 int k = 0, S = 0; for (k=0; k<100; k++) { if (k%2 == 0) S += k; else S -= k; } 你能帮我填写第一个条件吗?如何在比较中使用模数,并检查余数是否为0 附言:我还没有学会如何在循环中处理条件,所以iftrue/IfError部分只是我这方面的一个快速即兴创作,我不知道它是否有效。这一部分可以做得更好吗?教授通常不会给你布置涉及你还没有学过的东西的作业。对于一个

我的教授给了我一个任务,要我把这个C代码转换成汇编代码

int k = 0, S = 0;
for (k=0; k<100; k++)
{
if (k%2 == 0)
S += k;
else
S -= k;
}
你能帮我填写第一个条件吗?如何在比较中使用模数,并检查余数是否为0

附言:我还没有学会如何在循环中处理条件,所以iftrue/IfError部分只是我这方面的一个快速即兴创作,我不知道它是否有效。这一部分可以做得更好吗?

教授通常不会给你布置涉及你还没有学过的东西的作业。对于一个外部观察者(比如阅读这个问题的人),大多数情况下你没有注意到,或者你没有意识到所解释的是实现模运算的一种方法

x86组件中的模数可以通过除以两个数字获得。将divident放入某个寄存器,执行提供除数的某条指令,在该指令执行后,某个寄存器接收商,另一个寄存器接收余数。但这无关紧要,因为你可能还没有学会除法运算,这没关系,因为我们不打算使用除法

在x86汇编(以及任何其他相关的汇编)中,您可以非常轻松地计算除法的余数,而不必使用除法运算。2是2的幂。(2的1次方。)

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

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

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

“准确地说,如何实现这一点留给学生做练习。”

(试一试,如果你做不到,再发一个问题。)

关于JE/JNE部分,它实际上是错误的,因为当CX停止小于99时,
JL Loop1
指令将转到
ifError:
标签,这不是您想要的。您应该按照以下方式重写它:

    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
请注意,您并不完全想要
添加AX,CX
子AX,CX
,您想要
添加AX,MM
子AX,MM
,其中
MM
是CX模2,您仍在研究如何计算


另外请注意,我并不担保
CMP CX,99
后接
JL Loop1
是否正确,您还没有问过这一点,您可能稍后会遇到它,但这应该很容易理解。

测试CX,1
基于CX的最后一位设置零标志。在这种情况下,Equal或JZ对应于cx%2==0。用x-1掩蔽是取模的一种特殊情况,仅当x是2的幂时才适用。

问题的核心是
%2
只是一种低效的方式来表示
&1
)你真的应该看看指令参考。您可能会发现剩余部分存储在寄存器中;剩下的是模数。谢谢,但就像我说的,组装只是我课程的一小部分。我们只学过3-4个寄存器。我的教授在我的课堂上并没有教过直接使用剩余部分的寄存器。如果我用它,他可能会把它记为错误。谢天谢地,由于这大约是%2,我只需要找出它是偶数还是奇数。迈克的回答帮助我找到了一个可以接受的解决这个问题的方法。我想你的教授也不会接受
mov ax,-50
+
ret
,嗯?:-)关于
JE-iftrue
+
JNE-ifError
对:假设您删除了
JE-iftrue
行,ZF=1会发生什么情况。。。代码将通过
JNE
进入
iftrue:
带标签的指令
addax,CX
,因此您将获得与原始代码相同的结果,但您将保存一条条件跳转指令,这对性能有好处。它是关于选择一个if-else案例作为“默认”,并仅在非默认情况下跳出它。想想看。。。(或者更好的方法是,按照自己的方式编写,在debugger中单步检查指令,检查其工作原理,然后注释掉
JE
+debug)。非常感谢您提供的所有有用的输入。我知道JMP,但我对使用它犹豫不决,因为我们在课堂上没有讨论过它。无论如何,如果我想让代码有条理的话,这似乎是最好的方法。对于剩余进退两难的情况,是否可以使用
SHR MM,1
影响进位值,然后如果进位和
JNC iftrue
存在,则使用
JC IFERROWER
?我想到的另一种方法是
MOV-MM,CX
,然后使用
JPE-ifError
JPO-iftrue
?我自己无法确认这一点,因为我们没有使用任何汇编程序来运行我们的代码,只在纸上和笔上运行。
SHR-MM,1
是一种方法,但是您将暂时需要一个额外的寄存器(比如DX),因为您不想移动CX,因为您不想破坏它的值。Aki Suikkonen建议的
TEST CX,1
指令是一个更好的选择,因为它测试位0而不改变
    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