Estou tentando vincular esta função de montagem com este código c++:
.text
.global _Z7scambiaRiS_
_Z7scambiaRiS_:
pushq %rbp
mov %rsp, %rbp
mov (%rdi), %rax
mov (%rsi), %rcx
mov %rcx, (%rdi)
mov %rax, (%rsi)
leave
ret
.data
#include <iostream>
void extern scambia(int &a, int &b);
int main()
{
int a, b;
std::cin>>a>>b;
std::cout<<"a: "<<a<<" b: "<<b<<"\n";
scambia(a, b);
std::cout<<"a: "<<a<<" b: "<<b<<"\n";
return 0;
};
O assembly é uma versão intel x86-64.
O programa funciona, mas depois para com falha de segmentação. Aqui está a saída, fornecida como entrada 3 4
:
3 4
a: 3 b: 4
a: 4 b: 3
*** stack smashing detected ***: terminated
Aborted (core dumped)
Eu realmente não entendo como consegui comprometer a pilha, e mesmo depurando com o gdb não consegui descobrir o que deu errado
scambia
é declarado como tendo referências aint
, que é 4 bytes nesta plataforma. No entantoestá fazendo cargas e armazenamentos de 8 bytes, porque
rax
ercx
são registradores de 64 bits. Então cada um deles escreve 4 bytes além doint
que você passou, o que significa que outro espaço de pilha é sobrescrito, disparando o detector de quebra de pilha.Para usar a função de montagem como está, ela deve ser declarada em C++ como recebendo referências a
int64_t
ou algum outro tipo de 64 bits, e os tiposa,b
ajustados adequadamente. (long int
é de 64 bits em muitas plataformas x86-64, mas não em todas).Para manter a declaração como troca de dois
int
s, altere o código assembly para usar registradores de 32 bits para os dados que estão sendo movidos de e para a memória:Observe que
rdi
ersi
devem permanecer como estão, pois são ponteiros, que são 64 bits.