2016-04-02 3 views
0

На следующей неделе у меня есть следующий проект, и я провел последние 2 дня, выясняя, как сделать n-й корень.x86 Assembly (NASM) Как nth root или повысить значение с плавающей запятой с долей

Мне нужно смоделировать геометрическое среднее в сборке NASM.

Я знаю, что у FPU есть инструкция для Square Rooting, но это не займет у меня далеко.

В настоящее время я могу вводить столько входных данных, сколько хочу, и это умножает их без проблем. Но я застрял с частью «n-го корня», поскольку я не знаю, как это сделать с NASM.

Это мой текущий код:

global _main 
    extern _printf, _scanf, _system 

    section .text 

    _main: 
    mov ebp, esp; for correct debugging 
push clr 
call _system 
add esp, 4 

    ; start of INITIALIZE 
    ;printf("Enter number of elements") 
push print1 
call _printf 
add esp, 4 
    ; scanf number of elements 
push n 
push scan1 
call _scanf 
add esp, 8 

    ; printf("enter n integers") 
    push dword [n] 
push print2 
call _printf 
add esp, 8 

    fld qword [n2] 


    ; scan first element 
    push n2 
    push scan2 
    call _scanf 
    add esp, 8 

    fld qword [n2] 

    JE J1 

    MOV EBX, 1 

    CMP EBX, [n] 
    JE J1 

    L1: 

    push n2 
    push scan2 
    call _scanf 
    add esp, 8 

    fld qword [n2] 
    fmul st1, st0 
    fstp qword [ans] 

    INC EBX 
    CMP EBX, dword [n] 
    JE J1 
    LOOP L1 

    J1: 

    fst qword [ans] 

    push dword [ans+4] 
    push dword [ans] 
    push print3 
    call _printf 
    add esp, 12 

    mov dword [data8], n 

    fld qword [data7] 
    fld qword [data8] 

    fdiv st1, st0 

    fstp qword [ans] 


    fst qword [ans] 

    push dword [ans+4] 
    push dword [ans] 
    push print3 
    call _printf 
    add esp, 12 

    xor eax, eax 
    ret 

    section .data 
    clr  db "cls", 0 
    print1 db "Enter the number of elements:", 13,10,0 
    scan1 db "%d" , 0 
    scan2 db "%lf" , 0 
    n  dd 0 
    n2  dq 0.0 
    n3  dq 0.0 
    print2 db "Enter %d values:", 13,10,0 
    print3 db "Value is %g", 13, 10,0 
    data8 dq 3.0 
    ans  dq 0.0 
    loopstart dq 1.0 
    data7 dq 1.0 

Или также можно использовать внешнюю функцию C для извлечения корня п-й?

EDIT: Пытается использовать _pow от C. У меня есть этот код, но он не работает, может кто-то помочь?

 LEA ESI, [return] 

     push ESI 
     push dword [pushingthing+4] 
     push dword [pushingthing] 
     push dword [ans+4] 
     push dword [ans] 
     push pow1 
     call _pow 
     add esp, 24 

     section .data 

     return dq 0.0 
     pushingthing dq 2.0 
     pow1  dd "%g, %g", 13, 10, 0 

Делая это, потому что мощн (в C) имеет формат Pow (х, у), которые оба имеют двойной и возвращает двойное значение. Пожалуйста, проверьте.

+0

Конечно, вы можете использовать функцию '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ', зная, что' n'-й корень такой же, как и значение '1/n'. В сборке вы можете использовать логарифмы. – Jester

+0

Я до сих пор не совсем понимаю, как передавать значения с плавающей запятой функции C, которая имеет возвращаемое значение. Возможно ли, чтобы вы научили меня? Я искал в Интернете решение, но я в тупике. –

+0

Это описано в вызывающем соглашении для вашей платформы (о котором вы не упомянули). Как правило, вы передаете входные аргументы в стеке cpu и возвращаете результат в 'st (0)'. – Jester

ответ

4

Использование push для передачи аргументов, особенно в парном разряде, сделает вашу голову больной со всем обратным и наполовину :) Вы должны просто выделить место и использовать соответствующие команды mov. Вы все еще не сказали, в какой среде вы находитесь, но большинство из них возвращает результат в st(0) (т. Е. Стек с плавающей запятой). В качестве примера можно привести пример:

sub esp, 16   ; space for 2 doubles 
fld qword [x]  ; load 1st arg 
fstp qword [esp]  ; write to stack 
fld qword [y]  ; load 2nd arg 
fstp qword [esp+8] ; write to stack 
call _pow 
; result is now in st(0) print it 
mov dword [esp], fmt ; format string 
fstp qword [esp+4] ; pass result as arg 
call _printf 
add esp, 16   ; free stack space 

x: dq 16.0 
y: dq 0.25 
fmt: db "%g", 13, 10, 0 
+0

Святой моли он работает. Спасибо, и вы определенно сохраняете мою шкуру прямо сейчас. –