I need to solve this function in assembly but I have a problem with modulo. I have no idea why but it gives very strange results.
C code
#include <iostream>
extern "C" __int64 suma(int a, int b, int c, int d, int e, int f, int g, int h);
int main()
{
int a = 1, b = 1, c = 1, d = 1, e = 1, f = 1, g = 1, h = 1;
int wynik = suma(a, b, c, d, e, f, g, h);
std::cout << wynik;
}
assembly code
.CODE
_DATA SEGMENT
_DATA ENDS
_TEXT SEGMENT
PUBLIC suma
suma PROC
push rbp;
mov rbp, rsp;
imul rcx, rdx; // a * b
mov rax, r8; // c
xor rdx, rdx;
div r9; // c/d
mov r10, [rbp 6 * 8]; //e
sub r10, [rbp 7 * 8]; // e-f
mov r11, [rbp 8 * 8]; // g
add r11, [rbp 9 * 8]; //g h
add rcx, rax; // a * b c / d
sub rcx, r10; // a * b c / d - e - f
mov rdx, 0;
mov rax, rcx;
idiv r11;
mov rax, rdx;
pop rbp;
ret
suma ENDP
_TEXT ENDS
END
CodePudding user response:
Not sure if this is what you want, but when you have to write something in assembly, it is often a good idea to first have a look at what the compiler produces.
I'm not sure why you have an __int64
return type when you assign it anyway to an int
, but I'll respect your given function prototype.
__int64 suma(int a, int b, int c, int d, int e, int f, int g, int h);
The compiler I'll use is GCC in Linux, but your register usage follows the Windows ABI, so I'll change the declaration as follows.
__attribute__((ms_abi))
long long suma(int a, int b, int c, int d, int e, int f, int g, int h);
Now put your one line of code in the body, and see the output with optimization (-O3
).
{
return a * b c / d - (e - f) % (g h);
}
suma:
mov eax, r8d
imul ecx, edx
mov r8d, DWORD PTR [rsp 64]
add r8d, DWORD PTR [rsp 56]
cdq
idiv r9d
add ecx, eax
mov eax, DWORD PTR [rsp 40]
sub eax, DWORD PTR [rsp 48]
cdq
idiv r8d
sub ecx, edx
movsx rax, ecx
ret
Finally make it look better, a bit more like human-written.
suma:
imul ecx, edx
mov eax, r8d
cdq
idiv r9d
add ecx, eax
mov eax, DWORD PTR [rsp 40]
sub eax, DWORD PTR [rsp 48]
cdq
mov r8d, DWORD PTR [rsp 56]
add r8d, DWORD PTR [rsp 64]
idiv r8d
sub ecx, edx
movsx rax, ecx
ret
Also, as a personal opinion, don't blindly write
push rbp;
mov rbp, rsp;
at the entry of every function. Cases where this part is necessary is rare in a practical sense.