Вызов NASM float в сборке x86 из C - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть пример .Для моей задачи мне нужно использовать float вместо int:

#include <stdio.h>

extern float my_pow(float base, float exp);

int main(int argc, char const *argv[]) {
  float base = 2.0, exp = 8.0;
  printf("Result: %f\n", my_pow(base, exp));
  return 0;
}

Сборка с использованием nasm и gcc:

nasm -f macho64 calc.asm
gcc -m64 -o main main.c calc.o

В качестве вывода я получаю это:

Result: 2.000000

Когда мой результат должен быть 256.0.Что я делаю не так?

ОБНОВЛЕНИЕ: мой asm-код не изменился

global _my_pow
section .text

_my_pow:
    push    rbp             ; create stack frame
    mov     rbp, rsp

    cmp     edi, 0          ; Check if base is negative
    mov     eax, 0          ; and return 0 if so
    jl      end

    mov     eax, edi        ; grab the "base" argument
    mov     edx, esi        ; grab the "exponent" argument

multiply:
    imul    eax, edi        ; eax * base
    sub     esi, 1          ; exponent - 1

    cmp     esi, 1          ; Loop if exponent > 1
    jg      multiply

end:
    pop     rbp             ; restore the base pointer
    ret                     ; return from procedure

1 Ответ

0 голосов
/ 02 мая 2018

Я хотел бы расширить ответ Питера, потому что то, что он говорит, может быть непонятным для начинающих.

В первой части вашего кода в _my_pow вы получаете первые два аргумента от edi и esi, что будет правильным для большинства функций x86_64. Однако это отличается от чисел с плавающей запятой. При работе с числами с плавающей запятой первый аргумент находится в регистре xmm0, а второй аргумент - в xmm1. Возвращаемое значение с плавающей запятой возвращается в xmm0.

Итак, что говорил Питер, так это то, что компилятор C поместит аргументы, которые вы предоставляете, в эти регистры (потому что это то, что прототип, который вы использовали + соглашение о вызовах требует от него). Поскольку вы не оперируете ими в своем коде, вы просто получаете аргумент base в xmm0 в конце. А это значит, что ваш base аргумент 2.0 возвращается в C в качестве возвращаемого значения.

Посмотрите инструкции, такие как "movss" и "mulss" онлайн, это те инструкции, которые вам нужно знать, чтобы сделать это правильно. (Ссылки на документы в теге x86 вики )

...