2017-08-10 4 views
3

J'ai essayé d'utiliser ces conseils pour ce problèmex86-64 NASM Linux. paramètre Fonction passage d'un tableau de type int déclaré en fonction en C++ fichier

For Linux programming arr[], n, &a, &b are passed in RDI, RSI, RDX and RCX.

et la sortie du programme ne résume pas les entiers dans le tableau correctement . Il produit un grand nombre qui est évidemment faux.

Les deux fichiers trouvés ci-dessous ont été modifiés à partir de la version 32 bits d'origine trouvée ici. http://mcs.uwsuper.edu/sb/224/Intro/c_asm.html

Ce que je veux est de compiler un fichier d'assemblage qui appelle un paramètre de fonction dans un fichier C++ appelé array.cpp puis lier le fichier objet résultant array.o avec g++. Le problème que je rencontre concerne le passage des registres appropriés sur la pile ou peut-être le nombre d'octets à ajouter pour chaque décalage sur le registre rsi (j'ai utilisé 8 puisque chaque élément de pile est 64 bits).

Il se pourrait aussi que le registre rbp est pas correctement chargé les décalages corrects de l'adresse du tableau et nombre d'éléments dans le tableau.

mov rcx, [rbp+24] ; array length 
mov rsi, [rbp+16] ; array address 

Quoi qu'il en soit, voici le fichier array.cpp et au-dessous est le fichier nasm, je l'ai appelé nasm_cpp.asm.

Ils compilent, lien et exécuter avec

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 
} 

C'est nasm_cpp.asm ci-dessous

;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 
     push rcx   ; save used registers 
     push rdi 
     push rsi 

     mov rcx, [rbp+24] ; array length 
     mov rsi, [rbp+16] ; array address 

     xor rax, rax  ; clear the sum value  
lp: add rax, [rsi]  ; fetch an array element 
     add rsi, 8   ; move to another element 
     loop lp    ; loop over all elements 

     pop rsi    ; restore used registers 
     pop rdi 
     pop rcx  
     pop rbp 
     ret     ; return to caller 
+2

Les paramètres sont transmis dans des registres sur x86-64. Google pour "SYS V ABI x64" –

+0

Ici, http://wiki.osdev.org/System_V_ABI indique "Les paramètres des fonctions sont passés dans les registres rdi, rsi, rdx, rcx, r8, r9,". Est-ce que ce que vous pensez pourrait le résoudre? Qu'en est-il du reg 'rcx' Comment devrais-je compter et sauvegarder les valeurs avant que la pile ne soit poussée? – pandoragami

+0

J'ai enlevé 'rcx'' push' et 'pop' et cela ne fonctionnait toujours pas. – pandoragami

Répondre

1

J'ai suivi les suggestions dans les commentaires ci-dessous la question ci-dessous et il fonctionne maintenant, le fichier cpp est le même que ci-dessus.

;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 
+2

Notez votre le code ne fonctionnera pas si la longueur du tableau est égale à 0. Ce problème dépend de vos spécifications. – Jester

+0

Je suppose que je pourrais mettre un 'jz outside_loop' conditionnel après' cmp rcx, 0'? – pandoragami

+1

Il y a aussi une instruction 'jecxz' – Jester