Nasm Величайший общий делитель

Я хочу написать программу, в которой вы вводите два числа и получаете Величайший общий делитель со следующим псевдокодом:

Euclid(a, b)
while (b != 0)
{
r = a mod b
a = b
b = r
}
return a

Это моя текущая версия, которая выдает мне ошибку:52: недопустимая комбинация кода операции и операндов.

%include "asm_io.inc"

segment .data
prompt1 db    "Enter a number: ", 0       
prompt2 db    "Enter another number: ", 0

segment .bss
input1  resd 1
input2  resd 1

segment .text
    global  asm_main
asm_main:
    enter   0,0               ; setup routine
    pusha

    mov     eax, prompt1      
    call    print_string
    call    read_int   
    push eax       

    mov     eax, prompt2       
    call    print_string
    call    read_int    
    push eax      


    call euclid

    call print_int



    popa
    mov     eax, 0            ; return back to C
    leave                     
    ret


    ; Function euclid

    euclid:
         push ebp
         mov ebp, esp

         mov ebx, [ebp+8]
         mov ecx, [ebp+12]



         _while: 
            div ecx,ebx
            mov ebx,ecx
            mov ecx,edx
            cmp ecx,0
            jz _end
            jmp _while
         _end: 
            mov eax,ebx

        pop ebp
        ret

Я совершенно новичок в сборке и NASM, и я надеюсь, что вы можете помочь мне найти ошибку или ложный синтаксис.

3 ответа

Здесь нет div ecx,ebx инструкция. Если вы хотите выполнить ecx/ebx тогда вы должны использовать div r/m32 форма, которая делит 64-битное количество, сформированное из edx а также eax по данному операнду. Таким образом, вам придется позаботиться, чтобы обнулить edx для 32-разрядного дивиденда (или используйте расширение знака cdq Инструкция по подписанным операциям). Код может выглядеть так:

xor edx, edx
mov eax, ecx
div ebx  ; eax = ecx / ebx, remainder in edx

В случае сомнений используйте ссылку на набор инструкций.

В вашем коде могут быть логические ошибки, я ответил только на вопрос, который вы задали.

Ошибка в вашем коде - это ваша логика. Вы должны вернуть 'r', а не 'a', и в цикле while вы должны сравнить значение 'a mod b' с нулем, а не 'b' с нулем. Также есть больше случаев, которые происходят из-за сравнения двух целых чисел, например, первое целое число может быть меньше или больше, чем второе. Вы также должны учитывать эти сравнения в своем алгоритме. Я вообще не знаю nasm или сборки, но вы должны попробовать этот псевдо-код ниже. 'Min (a, b)' - это функция, которую вы должны написать, которая возвращает минимум 'a' и 'b'. Я не знаю синтаксис nasm или сборки, но логика должна работать хорошо. Все самое лучшее!

 Euclid(a,b)

       if(min(a,b)==a){
             while (b mod a != 0) { 
                r = b mod a
                b = a
                a = r
             }
             return r
          }

        else{
               while(a mod b!=0){
                  r = a mod b
                  a = b
                  b = r
              }
               return r
          }

Это программа для вычисления наибольшего общего делителя с использованием встроенной сборки.

#include <stdio.h>

int gcd( int a, int b ) {
    int result ;
    /* Compute Greatest Common Divisor using Euclid's Algorithm */
    __asm__ __volatile__ ( "movl %1, %%eax;"
                          "movl %2, %%ebx;"
                          "CONTD: cmpl $0, %%ebx;"
                          "je DONE;"
                          "xorl %%edx, %%edx;"
                          "idivl %%ebx;"
                          "movl %%ebx, %%eax;"
                          "movl %%edx, %%ebx;"
                          "jmp CONTD;"
                          "DONE: movl %%eax, %0;" : "=g" (result) : "g" (a), "g" (b)
                          );

    return result ;
}

int main(int argc, const char * argv[])
{
    printf("%d \n", gcd(30, 50));
    return 0;
}

Вот где я нашел это, http://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C

Другие вопросы по тегам