如何正确地将 asm 文件链接到 c++?
这是一个硬件问题,我完成了所有编码,但我在将 asm 与 c++ 链接时遇到问题,我使用 Windows Visual Studio 2010,当我尝试编译时,我将 main 放在源文件中,将我的 asm 文件放在资源文件中它只是给了我一个链接错误
1>------ Build started: Project: clearArray, Configuration: Debug Win32 ------
1>clearArray.cpp
1>clearArray.obj : error LNK2019: unresolved external symbol _clearPointerOp referenced in function _main
1>clearArray.obj : error LNK2019: unresolved external symbol _clearIndexOp referenced in function _main
1>C:\Users\Joe Chen\documents\visual studio 2010\Projects\clearArray\Debug\clearArray.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
这个硬件的目标是使用索引方法和指针方法清除数组,然后优化生成的asm代码
请帮助!
这是我的代码: main.cppclearIndexOp.asmclearPointerOp.asm
// clear array using unoptimized code with index and pointers
#include<iostream>
#include<fstream>
#include"timer.h"
using namespace std;
extern "C" {void clearIndexOp(int A[], int size);}
extern "C" {void clearPointerOp(int *A, int size);}
const int size = 100000;
int A[size] = {0};
void clearIndex(int A[], int size)
{
for(int i=0; i<size; i++)
A[i]=0;
}
void clearPointer(int *A, int size)
{
int *p;
for(p=&A[0]; p<&A[size]; p++)
*p=0;
}
int main()
{
double timeIndex = 0;
double timeIndexOp = 0;
double timePointer = 0;
double timePointerOp = 0;
StopWatch time;
ofstream myfile;
myfile.open("results.txt");
for(int n=2000; n<1000000; n=n*2)
{
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearIndex(A, size);
time.stopTimer();
timeIndex = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearPointer(A, size);
time.stopTimer();
timePointer = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearIndexOp(A, size);
time.stopTimer();
timeIndexOp = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearPointerOp(A, size);
time.stopTimer();
timePointerOp = time.getElapsedTime();
myfile << "n is now: " << n << "\n";
myfile << "timeIndex is: " << timeIndex << "\n";
myfile << "timePointer is: " << timePointer << "\n";
myfile << "timeIndexOp is: " << timeIndexOp << "\n";
myfile << "timePointerOp is: " << timePointerOp << "\n";
}
myfile.close();
}
.386
.model flat
.stack
.code
global _clearIndexOp proc
_i$ = -8 ; size = 4
_A$ = 8 ; size = 4
_size$ = 12 ; size = 4
; {
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; for(int i=0; i<size; i++)
; initialize the variables
mov eax, 0 ; init i=0 to eax
mov ebx, DWORD PTR _size$[ebp] ; size stored in ebx for faster access than memory
mov ecx, DWORD PTR _A$[ebp] ; get base addr of array
jmp SHORT $LN3@clearIndex ; jump into the loop
$LN2@clearIndex:
add eax, 1 ; increase eax since eax=i
$LN3@clearIndex:
cmp eax, ebx ; check that i < size
jge SHORT $LN4@clearIndex ; exits if i >= size
; A[i]=0;
mov DWORD PTR [ecx+eax*4], 0 ; A[i]=0
jmp SHORT $LN2@clearIndex ; go back to loop body
; after removing useless/repetitive codes
; we shrunk this code from 10 instructions to only 5 instructions
$LN4@clearIndex:
; }
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_clearIndexOp ENDP
.386
.model flat
.stack
.code
global _clearPointerOp proc
_p$ = -8 ; size = 4
_A$ = 8 ; size = 4
_size$ = 12 ; size = 4
; {
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; int *p;
; for(p=&A[0]; p<&A[size]; p
; initialize the variables
mov eax, DWORD PTR _A$[ebp] ; base addr of the array
mov DWORD PTR _p$[ebp], eax ; init p = A[0]
mov ebx, DWORD PTR _p$[ebp] ; move p to ebx
mov ecx, DWORD PTR _size$[ebp] ; size stored in ecx for faster access from register
lea edx, DWORD PTR [ecx+eax*4] ; last index of array, A[size-1]
jmp SHORT $LN3@clearPoint ; jump into loop
$LN2@clearPoint:
add eax, 4 ; since it is pointer we increase eax by 4 to move to next element
$LN3@clearPoint:
cmp ebx, edx ; check that p < size
jae SHORT $LN4@clearPoint ; exit if p >= size
; *p=0;
mov DWORD PTR [ebx], 0
jmp SHORT $LN2@clearPoint
; after removing useless/repetitive codes
; we shrunk this code from 11 instructions to only 5 instructions
$LN4@clearPoint:
; }
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_clearPointerOp ENDP
this is a hw problem, ive done all the coding but im having trouble linking the asm with c++, im using windows visual studio 2010, i put the main in source files, and my asm files in the resources files, when i try to compiling it just gives me a linking error
1>------ Build started: Project: clearArray, Configuration: Debug Win32 ------
1>clearArray.cpp
1>clearArray.obj : error LNK2019: unresolved external symbol _clearPointerOp referenced in function _main
1>clearArray.obj : error LNK2019: unresolved external symbol _clearIndexOp referenced in function _main
1>C:\Users\Joe Chen\documents\visual studio 2010\Projects\clearArray\Debug\clearArray.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
the objective of this hw was to clear an array using index method and pointer method, then optimize the generated asm code
please help!!!
heres my codes:
main.cpp
// clear array using unoptimized code with index and pointers
#include<iostream>
#include<fstream>
#include"timer.h"
using namespace std;
extern "C" {void clearIndexOp(int A[], int size);}
extern "C" {void clearPointerOp(int *A, int size);}
const int size = 100000;
int A[size] = {0};
void clearIndex(int A[], int size)
{
for(int i=0; i<size; i++)
A[i]=0;
}
void clearPointer(int *A, int size)
{
int *p;
for(p=&A[0]; p<&A[size]; p++)
*p=0;
}
int main()
{
double timeIndex = 0;
double timeIndexOp = 0;
double timePointer = 0;
double timePointerOp = 0;
StopWatch time;
ofstream myfile;
myfile.open("results.txt");
for(int n=2000; n<1000000; n=n*2)
{
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearIndex(A, size);
time.stopTimer();
timeIndex = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearPointer(A, size);
time.stopTimer();
timePointer = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearIndexOp(A, size);
time.stopTimer();
timeIndexOp = time.getElapsedTime();
// put values into the array
for(int i=0; i<size; i++)
A[i]=i+rand()%10+1;
time.startTimer();
clearPointerOp(A, size);
time.stopTimer();
timePointerOp = time.getElapsedTime();
myfile << "n is now: " << n << "\n";
myfile << "timeIndex is: " << timeIndex << "\n";
myfile << "timePointer is: " << timePointer << "\n";
myfile << "timeIndexOp is: " << timeIndexOp << "\n";
myfile << "timePointerOp is: " << timePointerOp << "\n";
}
myfile.close();
}
clearIndexOp.asm
.386
.model flat
.stack
.code
global _clearIndexOp proc
_i$ = -8 ; size = 4
_A$ = 8 ; size = 4
_size$ = 12 ; size = 4
; {
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; for(int i=0; i<size; i++)
; initialize the variables
mov eax, 0 ; init i=0 to eax
mov ebx, DWORD PTR _size$[ebp] ; size stored in ebx for faster access than memory
mov ecx, DWORD PTR _A$[ebp] ; get base addr of array
jmp SHORT $LN3@clearIndex ; jump into the loop
$LN2@clearIndex:
add eax, 1 ; increase eax since eax=i
$LN3@clearIndex:
cmp eax, ebx ; check that i < size
jge SHORT $LN4@clearIndex ; exits if i >= size
; A[i]=0;
mov DWORD PTR [ecx+eax*4], 0 ; A[i]=0
jmp SHORT $LN2@clearIndex ; go back to loop body
; after removing useless/repetitive codes
; we shrunk this code from 10 instructions to only 5 instructions
$LN4@clearIndex:
; }
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_clearIndexOp ENDP
clearPointerOp.asm
.386
.model flat
.stack
.code
global _clearPointerOp proc
_p$ = -8 ; size = 4
_A$ = 8 ; size = 4
_size$ = 12 ; size = 4
; {
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; int *p;
; for(p=&A[0]; p<&A[size]; p
; initialize the variables
mov eax, DWORD PTR _A$[ebp] ; base addr of the array
mov DWORD PTR _p$[ebp], eax ; init p = A[0]
mov ebx, DWORD PTR _p$[ebp] ; move p to ebx
mov ecx, DWORD PTR _size$[ebp] ; size stored in ecx for faster access from register
lea edx, DWORD PTR [ecx+eax*4] ; last index of array, A[size-1]
jmp SHORT $LN3@clearPoint ; jump into loop
$LN2@clearPoint:
add eax, 4 ; since it is pointer we increase eax by 4 to move to next element
$LN3@clearPoint:
cmp ebx, edx ; check that p < size
jae SHORT $LN4@clearPoint ; exit if p >= size
; *p=0;
mov DWORD PTR [ebx], 0
jmp SHORT $LN2@clearPoint
; after removing useless/repetitive codes
; we shrunk this code from 11 instructions to only 5 instructions
$LN4@clearPoint:
; }
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_clearPointerOp ENDP
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题是您的 asm 没有被视为源文件。
修复方法:
1) 右键单击您的项目并选择“构建自定义”,然后选中 masm 旁边的框
2) 右键单击您的 .asm 文件,选择“属性”,然后将“项类型”更改为“Microsoft 宏汇编器”。
编辑#2:我现在看到您正在使用 VS 生成的 asm 代码的修改版本,而且几乎没问题。
只需从 PROC 声明中删除“global”,然后在 asm 文件末尾添加 END 即可。
这应该能让汇编正确组装和链接。但看起来你可能在clearPointerOp 中弄乱了一些东西,因为它最后进入了无限循环。一旦你的代码被编译和链接,你应该能够从那里弄清楚它。
The problem is your asm is not being treated as a source file.
To fix:
1) Right-click your project and choose Build Customizations, then check the box next to masm
2) Right-click your .asm files, choose Properties, then change the Item Type to Microsoft Macro Assembler.
Edit #2: I see now that you're using a modified version of the asm code generated by VS and it's almost okay.
Just remove "global" from the PROC declarations, and then add an END to the end of the asm files.
That should get the asm to assemble and link correctly. But it looks like you probably messed something up in clearPointerOp because it goes into an infinite loop at the end. You should be able to figure it out from there once your code is compiling and linking.
我认为我在 asm 代码中看到了许多错误和低效率,但首先,为什么不使用 memset() 标准 C 函数?
I think I'm seeing a number of errors and inefficiencies in the asm code, but first, why not use the memset() standard C function?
自从我也这样做以来已经很长时间了 - 但你似乎已经使用 C 调用约定导入了函数名称,这很好(删除 C++ 名称修饰)。
一些问题:
Been a long time since I had too - but you seem to have imported function names using C calling convention which is good (remove C++ name mangling).
Some questions: