我尝试使用汇编(FASM)程序作为C中的函数,但它似乎不工作,即使我链接了编译对象。有什么建议吗?
C程序:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
extern "C"
{
unsigned int __stdcall long_add(int*, int*, int*);
}
int main()
{
int testOne[3] = { 0x12345678, 0x04000000, 0xFFFFFFFF };
int testTwo[3] = { 0x12345678, 0x04000000, 0xFFFFFFFF };
int testOut[3] = {};
long_add(testOne, testTwo, testOut);
scanf;
}
组装功能:
include 'include\win32a.inc'
format MS COFF
public long_add as '_long_add@32'
section '.code' code readable executable
proc long_add IN_NUM1, IN_NUM2, OUT_NUM
start:
mov ecx, 3
clc
ADDING:
mov eax, [IN_NUM1+(ecx-1)*4]
mov ebx, [IN_NUM2+(ecx-1)*4]
adc eax, ebx
mov [OUT_NUM+(ecx-1)*4], eax
loop ADDING
ret
endp
链接证明:https://i.stack.imgur.com/au0jy.png
编辑:我试着把数组地址移到寄存器中,最后得到了下面的代码:
format MS COFF
public long_add as '_long_add@12'
section '.code' code readable executable
proc long_add IN_NUM1, IN_NUM2, OUT_NUM
start:
mov ecx, 3
clc
mov edi, [IN_NUM1]
mov esi, [IN_NUM2]
ADDING:
mov eax, [edi+(ecx-1)*4]
mov ebx, [esi+(ecx-1)*4]
adc eax, ebx
push eax
loop ADDING
mov esi, [OUT_NUM]
mov ecx, 3
POPPING:
pop eax
mov [esi], eax
inc esi
loop POPPING
ret
endp
虽然这段代码可以正常工作,比如程序不会崩溃,但是当我尝试将{0x 12345678,0x 04000000,0xFFFFFFFF}和{0x 87654321,0x 02000000,0x 000001}相加时,它返回{409,0,0}。
1条答案
按热度按时间js81xvg61#
注解已经指出了stdcall的命名错误。导致错误输出的原因是您使用
inc esi
来循环OUT_NUM
,而您应该使用add esi, 4
,就像您在加法循环中所做的那样,因为每个int
是4个字节。或者,您可以使用stosd
,或者直接存储在加法循环中。我还建议在函数的开头压入
esi
和edi
,并在函数的结尾弹出它们(相反的顺序!),因为我非常确定这些是非易失性(被调用方保存的)寄存器,所以C编译器可能会假设它们没有被修改。评论告诉你的关于用
ret 3*4
替换ret
的内容是不正确的,因为stdcall模式下的proc
宏会自动为你做这件事。