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