C++ x86-64 Linux NASM。在C+;中声明为函数的int数组类型的函数参数传递+;文件
我试着用这个建议来解决这个问题 程序的输出不能正确地将数组中的整数相加。它输出一个明显错误的大数字 下面找到的两个文件是从这里找到的原始32位版本修改而来的 < >我想编译一个汇编文件,它调用一个C++文件中的函数参数,称为<代码>数组.CPP < /C> >,然后将生成的目标文件<代码>数组.O./COD>与<代码> G++< /C> >链接。p> 我遇到的问题要么是将正确的寄存器传递到堆栈上,要么是为C++ x86-64 Linux NASM。在C+;中声明为函数的int数组类型的函数参数传递+;文件,c++,linux,assembly,stack,function-parameter,C++,Linux,Assembly,Stack,Function Parameter,我试着用这个建议来解决这个问题 程序的输出不能正确地将数组中的整数相加。它输出一个明显错误的大数字 下面找到的两个文件是从这里找到的原始32位版本修改而来的 < >我想编译一个汇编文件,它调用一个C++文件中的函数参数,称为数组.CPP < /C> >,然后将生成的目标文件数组.O./COD>与 G++< /C> >链接。p> 我遇到的问题要么是将正确的寄存器传递到堆栈上,要么是为rsi寄存器上的每个偏移量添加的字节数(因为每个堆栈元素是64位,所以我使用了8) 也可能是rbp寄存器没有正确加
rsi
寄存器上的每个偏移量添加的字节数(因为每个堆栈元素是64位,所以我使用了8)
也可能是rbp
寄存器没有正确加载数组地址和数组中元素数的正确偏移量
mov rcx, [rbp+24] ; array length
mov rsi, [rbp+16] ; array address
总之,这里是array.cpp
文件,下面是nasm文件,我称之为nasm\u cpp.asm
它们使用
nasm -f elf64 nasm_cpp.asm -o array.o
g++ -m64 array.cpp array.o
./a.out
#include <iostream>
using namespace std;
extern "C" int array(int a[], int length); // external ASM procedure
int main()
{
int a[] = { 10, 10}; // array declaration
int array_length = 2; // length of the array
int sum = array(a, array_length); // call of the ASM procedure
cout << "sum=" << sum << endl; // displaying the sum
}
我遵循了问题下方评论中的建议,现在可以使用了,cpp文件与上面的相同
;nasm -f elf64 nasm_cpp.asm -o array.o
;g++ -m64 array.cpp array.o
;./a.out
global array ; required for linker and NASM
section .text ; start of the "CODE segment"
array:
push rbp
mov rbp, rsp ; set up the rBP
mov rcx, rsi ; array length
mov rsi, rdi ; array address
xor rax, rax ; clear the sum value
lp: add eax, [rsi] ; fetch an array element
add rsi, 4 ; move to another element
loop lp ; loop over all elements
pop rbp
ret ; return to caller
参数在x86-64上的寄存器中传递。谷歌搜索“SYS V ABI x64”,这里说函数的
参数在寄存器rdi、rsi、rdx、rcx、r8、r9、
中传递。这就是你认为可以解决的问题吗?那么rcx
reg.呢。在堆栈推送之前,我应该如何计数并保存其中的值?我删除了rcx
push
和pop
,但这仍然不起作用。您不需要推送和弹出rcx、rsi、rdi,因为它们是可由函数更改且不需要保留的易失性寄存器。你可以从中看出这一点。除此之外,最简单的修复方法是更改为mov-rcx,rsi;数组长度
mov-rsi,rdi;数组地址
。由于要添加32位整数,您需要将添加rax,[rsi]
更改为添加eax,[rsi]
并将4添加到地址,而不是8-更改添加rsi,8
到添加rsi,4
。循环指令可能效率低下(尽管它将您与RCX联系在一起,但它仍然可以工作。您可以通过使用RDI作为指针而不是RSI来简化代码,从而消除额外的移动。您甚至不需要堆栈帧,因此可以删除开始时的push rbp mov rbp,rsp
,以及pop rbp
。请注意,如果ar射线长度为零。这是否是一个问题取决于您的规格。我想我可以在cmp rcx,0
之后放置一个jz外循环
条件。还有一个jecxz
指令点!@Jester
;nasm -f elf64 nasm_cpp.asm -o array.o
;g++ -m64 array.cpp array.o
;./a.out
global array ; required for linker and NASM
section .text ; start of the "CODE segment"
array:
push rbp
mov rbp, rsp ; set up the rBP
mov rcx, rsi ; array length
mov rsi, rdi ; array address
xor rax, rax ; clear the sum value
lp: add eax, [rsi] ; fetch an array element
add rsi, 4 ; move to another element
loop lp ; loop over all elements
pop rbp
ret ; return to caller