C++ x86-64 Linux NASM。在C+;中声明为函数的int数组类型的函数参数传递+;文件

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寄存器没有正确加

我试着用这个建议来解决这个问题

程序的输出不能正确地将数组中的整数相加。它输出一个明显错误的大数字

下面找到的两个文件是从这里找到的原始32位版本修改而来的

< >我想编译一个汇编文件,它调用一个C++文件中的函数参数,称为<代码>数组.CPP < /C> >,然后将生成的目标文件<代码>数组.O./COD>与<代码> G++< /C> >链接。p> 我遇到的问题要么是将正确的寄存器传递到堆栈上,要么是为
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