В вашем коде есть синтаксическая ошибка, связанная с неправильным использованием скобок и отсутствием return для функций на C, вызывающих ассемблер. Также стоит обратить внимание на то, что функции calc_mean и calc_stddev написаны на языке ассемблера внутри функции, и они не возвращают значение явно, из-за чего компилятор не знает, что возвращать.
Исправьте функции так, чтобы функции возвращали результат через return, а также убедитесь, что ассемблерный код правильно завершает работу и возвращает значение.
Ниже исправленный и дополненный вариант кода:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Объявление функции ассемблера для вычисления среднего арифметического
extern double calc_mean(double *arr, int n);
// Объявление функции ассемблера для вычисления стандартного отклонения
extern double calc_stddev(double *arr, int n, double mean);
int main() {
// Декларируем массив для хранения значений
double arr[100];
// Считываем размер массива
int n;
printf("Введите размер массива: ");
scanf("%d", &n);
// Считываем значения массива
printf("Введите элементы массива: ");
for (int i = 0; i < n; i++) {
scanf("%lf", &arr[i]);
}
// Вычисляем среднее арифметическое с помощью функции ассемблера
double mean = calc_mean(arr, n);
// Вычисляем стандартное отклонение с помощью функции ассемблера
double stddev = calc_stddev(arr, n, mean);
// Выводим результаты
printf("Среднее арифметическое: %.2f\n", mean);
printf("Стандартное отклонение: %.2f\n", stddev);
return 0;
}
// Функция ассемблера для вычисления среднего арифметического
double calc_mean(double *arr, int n) {
double result;
asm(
"xor %%rax, %%rax;" // rax = сумма
"xor %%rbx, %%rbx;" // rbx = индекс (счётчик)
"mov %%rsi, %%rdi;" // rdi = arr
"cvtsi2sd %%rsi, %%xmm0;" // n в xmm0 (если требуется)
"mov %%rdx, %%rcx;" // n в rcx
"pxor %%xmm1, %%xmm1;" // xmm1 = 0 для суммы
"1:"
"cmp %%rbx, %%rcx;"
"jge 2f;"
// Загружаем arr[rbx]
"movsd (%%rdi, %%rbx, 8), %%xmm2;"
"addsd %%xmm2, %%xmm1;"
"inc %%rbx;"
"jmp 1b;"
"2:"
// Делим сумму на n
"mov %%rcx, %%rax;"
"cvtsi2sd %%rax, %%xmm3;"
"divsd %%xmm3, %%xmm1;"
// Переносим результат из xmm1 в переменную result
"movsd %%xmm1, %0;"
: "=m" (result) // вывод
:
: "rax", "rbx", "rcx", "xmm0", "xmm1", "xmm2", "xmm3"
);
return result;
}
// Функция ассемблера для вычисления стандартного отклонения
double calc_stddev(double *arr, int n, double mean) {
double result;
asm(
"xor %%rax, %%rax;" // rax = сумма квадратов отклонений
"xor %%rbx, %%rbx;" // rbx = индекс
"mov %%rsi, %%rdi;" // rdi = arr
"cvtsi2sd %%rsi, %%xmm0;" // n
"mov %%rdx, %%rcx;" // n
"movsd %2, %%xmm2;" // mean
"pxor %%xmm1, %%xmm1;" // xmm1 = 0 для суммы квадратов
"1:"
"cmp %%rbx, %%rcx;"
"jge 2f;"
// Загружаем arr[rbx]
"movsd (%%rdi, %%rbx, 8), %%xmm3;"
// Вычитаем среднее
"subsd %%xmm2, %%xmm3;"
// Возводим в квадрат
"mulsd %%xmm3, %%xmm3;"
// Складываем в сумму
"addsd %%xmm3, %%xmm1;"
"inc %%rbx;"
"jmp 1b;"
"2:"
// Делим сумму квадратов на n
"mov %%rcx, %%rax;"
"cvtsi2sd %%rax, %%xmm4;"
"divsd %%xmm4, %%xmm1;"
// Вычисляем квадратный корень
"sqrtsd %%xmm1, %%xmm1;"
// Переносим результат в переменную result
"movsd %%xmm1, %0;"
: "=m" (result)
: "r" (arr), "m" (mean)
: "rax", "rbx", "rcx", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"
);
return result;
}
Обратите внимание:
- В ассемблерных функциях нужно явно возвращать значение через переменную, которая далее возвращается из функции.
- Используются инструкции
movsdдля работы с double, и правильные регистры для x86-64. - В вашем исходном коде были недочёты, связанные с отсутствием
returnи неправильной структурой ассемблерных вставок.
Также стоит проверить правильность сборки и компиляции с опциями, поддерживающими встроенный ассемблер (-masm=intel и т.п.).
Если нужна более подробная помощь по сборке или другим аспектам — скажите!