这是我的.CPP文件
#include <iostream>
using namespace std;
extern "C" void KeysAsm(int arr[], int n, int thetha, int rho);
// Keep this and call it from assembler
extern "C"
void crim(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp+2;
}
// Translate this into Intel assembler
void KeysCpp(int arr[], int n, int thetha, int rho){
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
crim(&arr[j], &arr[j + 1]);
}
}
arr[i]= arr[i] + thetha / rho * 2 - 4;
}
}
// Function to print an array
void printArray(int arr[], int size){
int i;
for (i = 0; i < size; i++)
cout << arr[i] << "\n";
cout << endl;
}
int main() {
int gamma1[]{
9,
270,
88,
-12,
456,
80,
45,
123,
427,
999
};
int gamma2[]{
900,
312,
542,
234,
234,
1,
566,
123,
427,
111
};
printf("Array:\n");
printArray(gamma1, 10);
KeysAsm(gamma1, 10, 5, 6);
printf("Array Result Asm:\n");
printArray(gamma1, 10);
KeysCpp(gamma2, 10, 5, 6);
printf("Array Result Cpp:\n");
printArray(gamma2, 10);
}
我想做的是,将 KeysCpp 函数转换为汇编语言,并从这个.CPP文件中调用它。我想保留.CPP中的 crim 函数,而只转换 KeysCpp。
这是我的.ASM文件
PUBLIC KeysAsm
includelib kernel32.lib
_DATA SEGMENT
EXTERN crim:PROC
_DATA ENDS
_TEXT SEGMENT
KeysAsm PROC
push rbp
mov rbp, rsp
sub rsp, 40
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-28], esi
mov DWORD PTR [rbp-32], edx
mov DWORD PTR [rbp-36], ecx
mov DWORD PTR [rbp-4], 0
jmp L3
L3:
mov eax, DWORD PTR [rbp-28]
sub eax, 1
cmp DWORD PTR [rbp-4], eax
jl L7
L4:
mov eax, DWORD PTR [rbp-28]
sub eax, DWORD PTR [rbp-4]
sub eax, 1
cmp DWORD PTR [rbp-8], eax
jl L6
L5:
add DWORD PTR [rbp-8], 1
L6:
mov eax, DWORD PTR [rbp-8]
cdqe
lea rdx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rax, rdx
mov edx, DWORD PTR [rax]
mov eax, DWORD PTR [rbp-8]
cdqe
add rax, 1
lea rcx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rax, rcx
mov eax, DWORD PTR [rax]
cmp edx, eax
jle L5
mov eax, DWORD PTR [rbp-8]
cdqe
add rax, 1
lea rdx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rdx, rax
mov eax, DWORD PTR [rbp-8]
cdqe
lea rcx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rax, rcx
mov rsi, rdx
mov rdi, rax
call crim
L7:
mov DWORD PTR [rbp-8], 0
jmp L4
KeysAsm ENDP
_TEXT ENDS
END
我正在使用Visual Studio 2017运行此项目。
运行此代码时出现下一个错误。
MatrixMultiplication.exe中0x00007FF74B0E429C处的未处理异常:堆栈Cookie检测代码检测到基于堆栈的缓冲区溢出。发生
1条答案
按热度按时间y4ekin9u1#
您的asm看起来像是预期使用x86-64 System V呼叫惯例,而args则使用RDI、ESI、EDX、ECX。但是您说您是使用Visual Studio进行编译,因此编译器产生的程式码会使用Windows x64呼叫惯例:RCX、EDX、R8D、R9D。
当调用
crim
时,它可以使用影子空间(返回地址上方的32个字节,您没有为它保留空间)。看起来您是从未经优化的编译器输出中得到这个asm的,可能是从使用GCC for Linux的https://godbolt.org/z/ea4MPh81r中得到的,在为非Windows目标编译时没有使用
-mabi=ms
覆盖默认的-mabi=sysv
。底部是jmp
而不是ret
?可能是不同于12.2的GCC版本,因为标签编号和代码不完全匹配。(The未优化编译器输出的标志是所有从
[rbp-whatever]
重新加载,并在使用int
索引cdqe
数组之前重新进行符号扩展。人类应该知道int
必须是非负的。特别是GCC,像.L1:
等编号标签在您刚刚删除.
的地方,以及在调试版本中尽可能多地大量使用RAX
。并且像lea rdx, [0+rax*4]
这样的选择用于复制和移位,以及它在英特尔语法中用于打印该指令的确切语法与GCC匹配。)若要编译Windows x64的单一函式,请将它隔离,并只为编译器提供它所呼叫之任何函式的原型
然后在Godbolt上,使用
gcc -O3 -mabi=ms
,或使用MSVC,它总是针对Windows。https://godbolt.org/z/Mj5Gb54b5显示GCC和MSVC,并启用优化。不幸的是,GCC没有提升
thetha / rho * 2 - 4
循环不变式,而是每次都重做idiv
。看起来像是一个明显的优化,因为这些都是本地变量,它们的地址根本没有被取到,而且它在寄存器中保留了thetha
(拼写错误是theta
?)和rho
。所以MSVC在这里效率更高。Clang也错过了这个优化。