У меня есть Ubuntu 16.04, x86_64 arch, 4.15.0-39-generic версия ядра.GCC 8.1.0
Я пытался переписать эту функцию (с первого поста https://groups.google.com/forum/#!topic/comp.lang.c++.moderated/qHDCU73cEFc) с диалекта Intel на AT & T. И у меня не получилось.
namespace atomic {
__declspec(naked)
static void*
ldptr_acq(void* volatile*) {
_asm {
MOV EAX, [ESP + 4]
MOV EAX, [EAX]
RET
}
}
__declspec(naked)
static void*
stptr_rel(void* volatile*, void* const) {
_asm {
MOV ECX, [ESP + 4]
MOV EAX, [ESP + 8]
MOV [ECX], EAX
RET
}
}
}
Тогда я написалпростая программа, чтобы получить тот же указатель, который я передаю внутрь. Я установил GCC версии 8.1 с поддерживаемыми голыми атрибутами (https://gcc.gnu.org/gcc-8/changes.html «Порт x86 теперь поддерживает атрибут голой функции») для функций.помните, этот атрибут говорит компилятору не создавать пролог и эпилог функции, и я могу сам взять параметры из стека и вернуть их. Код: (не работает с segfault)
#include <cstdio>
#include <cstdlib>
__attribute__ ((naked))
int *get_num(int*) {
__asm__ (
"movl 4(%esp), %eax\n\t"
"movl (%eax), %eax\n\t"
"ret"
);
}
int main() {
int *i =(int*) malloc(sizeof(int));
*i = 5;
int *j = get_num(i);
printf("%d\n", *j);
free(i);
return 0;
}
затем я попытался использовать 64-битные регистры: (не работает с segfault)
__asm__ (
"movq 4(%rsp), %rax\n\t"
"movq (%rax), %rax\n\t"
"ret"
);
И только после того, как я вынул значение из регистра rdi - все заработало.
__asm__ (
"movq %rdi, %rax\n\t"
"ret"
);
Почему я не смог выполнить передачу через регистр стека? Возможно, я допустил ошибку. Скажите, пожалуйста, где мой сбой?