我对汇编非常陌生,我正在尝试为x86构建一个非常简单的程序,它将值放入EAX:
(没什么?)如果EBX可以除以2 ^ n且n> 3
1,如果EBX可以除以2 ^ 3 - > 8
2,如果EBX可以除以2 ^ 2 - > 4
3如果EBX可以除以2 ^ 1 - > 2
如果EBX是奇数,则0
所以我已经构建了这个程序并对其进行了测试,一切运行正常,但我不知道如何查看它是否真的按照我的意愿去做。我无法找到输出注册表当前价值的任何方法,而且对互联网的广博知识只能为我提供一些并不能带我走远的部分答案。
对我来说,一个主要问题是我不确定ret语句是否返回到_main函数,或者只是" break"执行。后者是我想要的。那么我有办法检查我的程序是否正常工作吗?
section .text
global _main
_main:
MOV EAX, EBX
MOV ECX, 16
DIV ECX
CMP DX, 0 ;Op=word (1,0,0,0,0), AX := DX:AX/Op, DX -> rest
JE end0 ;If number%16 == 0
MOV EAX, EBX
MOV ECX, 8
DIV ECX
CMP DX, 0 ;Op=word (1,0,0,0), AX := DX:AX/Op, DX -> rest
JE end8 ;If number%8 == 0
MOV EAX, EBX
MOV ECX, 4
DIV ECX
CMP DX, 0 ;Op=word (1,0,0), AX := DX:AX/Op, DX -> rest
JE end4 ;If number%4 == 0
MOV EAX, EBX
MOV ECX, 2
DIV ECX
CMP DX, 0 ;Op=word (1,0), AX := DX:AX/Op, DX -> rest
JE end2 ;If number%2 == 0
JMP end1 ;
end8:
MOV EAX, 3
ret
end4:
MOV EAX, 2
ret
end2:
MOV EAX, 1
ret
end1:
MOV EAX, 0
ret
end0:
ret
答案 0 :(得分:1)
您可以使用调试器单步执行代码,并在每一步检查寄存器和内存。
关于ret
的问题:它与call
相对应,粗略地说它会在最近的call
之后继续。 (这是一个简化的视图。)请注意,您使用简单的条件跳转,例如je end0
,因此ret
中的end0
将不会返回到该位置。相反,它将退出你的_main
并继续任何人调用它,这可能是C启动代码。实际上它会退出_main
。据我所知,这正是你想要的。
PS:您使用DIV
错误,它只是偶然的。它隐含地使用EDX
作为被除数的高32个字,所以你应该总是将它归零为32位无符号除法。甚至你的评论都说,尽管它描述了16位版本的操作。
另请注意,要检查2的幂的可除性,通常使用按位运算,而不是除法。