汇编 64 位函数 a*b+c/d-(e-f)%(g+h)
Assembly 64 bits function a*b+c/d-(e-f)%(g+h)
我需要在汇编中解决这个函数,但我遇到了模数问题。我不知道为什么,但它给出了非常奇怪的结果。
C++代码
#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;
}
汇编代码
.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
不确定这是否是您想要的,但是当您必须在汇编中编写某些内容时,首先查看编译器生成的内容通常是个好主意。
我不确定为什么你有一个 __int64
return 类型,但你仍然将它分配给 int
,但我会尊重你给定的函数原型。
__int64 suma(int a, int b, int c, int d, int e, int f, int g, int h);
我将使用的编译器是 Linux 中的 GCC,但是您的寄存器使用遵循 Windows ABI,因此我将按如下方式更改声明。
__attribute__((ms_abi))
long long suma(int a, int b, int c, int d, int e, int f, int g, int h);
现在将您的一行代码放入主体中,并查看经过优化的输出 (-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
终于改得好看了,有点像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
另外,作为个人意见,不要盲目写
push rbp;
mov rbp, rsp;
在每个函数的入口处。在实际意义上需要这部分的情况很少见。
我需要在汇编中解决这个函数,但我遇到了模数问题。我不知道为什么,但它给出了非常奇怪的结果。
C++代码
#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;
}
汇编代码
.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
不确定这是否是您想要的,但是当您必须在汇编中编写某些内容时,首先查看编译器生成的内容通常是个好主意。
我不确定为什么你有一个 __int64
return 类型,但你仍然将它分配给 int
,但我会尊重你给定的函数原型。
__int64 suma(int a, int b, int c, int d, int e, int f, int g, int h);
我将使用的编译器是 Linux 中的 GCC,但是您的寄存器使用遵循 Windows ABI,因此我将按如下方式更改声明。
__attribute__((ms_abi))
long long suma(int a, int b, int c, int d, int e, int f, int g, int h);
现在将您的一行代码放入主体中,并查看经过优化的输出 (-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
终于改得好看了,有点像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
另外,作为个人意见,不要盲目写
push rbp;
mov rbp, rsp;
在每个函数的入口处。在实际意义上需要这部分的情况很少见。