admin管理员组文章数量:1418706
I wrote a code in ASM to calculate the reverse number. For example: input: 123, the result should be 321. The ebx register should have the result, but it aways shows 0. Also, I have an exception "Privileged instruction". I attached an image with the exception. Here is the code:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int main() {
int nb;
cout << "nb=";
cin >> nb;
_asm {
mov eax, nb;
mov ebx, 0;
mov ecx, 10;
_check_while:
cmp eax, 0;
je _outside_while;
mov edx, 0;
div ecx;
xchg eax, ebx;
mul ecx;
add eax, edx;
xchg eax, ebx;
jmp _check_while;
_outside_while:
mov nb, ebx;
}
cout << "Result is" << " " << nb;
return 0;
}
I wrote a code in ASM to calculate the reverse number. For example: input: 123, the result should be 321. The ebx register should have the result, but it aways shows 0. Also, I have an exception "Privileged instruction". I attached an image with the exception. Here is the code:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int main() {
int nb;
cout << "nb=";
cin >> nb;
_asm {
mov eax, nb;
mov ebx, 0;
mov ecx, 10;
_check_while:
cmp eax, 0;
je _outside_while;
mov edx, 0;
div ecx;
xchg eax, ebx;
mul ecx;
add eax, edx;
xchg eax, ebx;
jmp _check_while;
_outside_while:
mov nb, ebx;
}
cout << "Result is" << " " << nb;
return 0;
}
Share
Improve this question
edited Jan 29 at 19:49
Peter Cordes
368k49 gold badges717 silver badges982 bronze badges
asked Jan 29 at 19:23
Alex544Alex544
354 bronze badges
4
|
2 Answers
Reset to default 1Your fot that mul ecx
leaves the widened product in EDX:EAX. Because of it, the remainder that you got before, from div ecx
, is no longer available. Just change the order of the operations. This will also save you from having to zero the EDX register before doing the division. Next code assumes that the reversed number never exceeds the unsigned dword range [0,4GB-1]:
_asm {
push ebx;
mov eax, nb;
xor ebx, ebx;
test eax, eax;
jz _done;
mov ecx, 10;
_more:
xchg eax, ebx;
mul ecx;
xchg eax, ebx; <<<< EDX is 0
div ecx;
add ebx, edx;
test eax, eax;
jnz _more;
_done:
mov nb, ebx;
pop ebx;
}
What is missing is a check for overflow. Consider eg. a number like 2,000,000,009 that once reversed can not fit in a 32-bit register. Next code checks for this and just doesn't update the nb variable. You pick whatever action you need in this case:
_asm {
push ebx;
mov eax, nb;
xor ebx, ebx;
test eax, eax;
jz _done;
mov ecx, 10;
_more:
xchg eax, ebx;
mul ecx;
jc _fail;
xchg eax, ebx; <<<< EDX is 0
div ecx;
add ebx, edx;
jc _fail;
test eax, eax;
jnz _more;
_done:
mov nb, ebx;
_fail:
pop ebx;
}
Your nb variable is an int
, so there's also signed overflow to consider! Take eg. a positive number like 1,000,000,004 that once reversed does fit in a 32-bit register, but that will not really reveal itself as 4,000,000,001.
This code should work:
__asm {
mov eax, dword ptr [nb]
mov ebx, 10
xor ecx, ecx
test eax, eax
je bail_out
while_loop:
xor edx, edx
imul ecx, ecx, 10
div ebx
add ecx, edx
test eax, eax
jne while_loop
bail_out:
mov dword ptr [nb], ecx
}
If you are in doubt, then just write it in C and let the compiler generate it for you by adding the /FAs
command line switch or setting the option to generate assembly with source code to and read it to understand how it works.
Note that this code is not fully optimized for demonstration purposes (it was generated with /O1
optimization level and it even used a stack location in the loop but I switched it to use ebx
instead). At /O2
and above compiler will use mul
, shr
, and lea
to avoid costly div
instruction.
If you want to learn assembler then you need to learn the various forms of each instruction and their parameters. I suggest grabbing a copy of Intel SDM.
本文标签: assemblyAssembler code doesn39t workreverse numberStack Overflow
版权声明:本文标题:assembly - Assembler code doesn't work - reverse number - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745281780a2651463.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
div ecx
can't #DE fault with ECX=10, and none of your instructions modify ECX. (And that wouldn't be a #GP(0) privileged instruction problem anyway.) – Peter Cordes Commented Jan 29 at 19:52mul ecx
overwritesedx
. You might want to useimul eax, ecx
. – Jester Commented Jan 29 at 19:56mul
so I think you could simplify by removing thexchg
s and doimul ebx, ecx
. Oh wait, you are reading EDX aftermul
? Probably you were expecting it to still hold the remainder fromdiv
. But actually it will be zero for small inputs where the high half of the 32x32 => 64-bit wideningmul ecx
is zero. – Peter Cordes Commented Jan 29 at 19:56