【问题标题】:Nasm Greatest common divisorNasm 最大公约数
【发布时间】:2013-06-02 21:36:45
【问题描述】:

我想写一个程序,你输入两个数字并得到最大公约数 使用以下伪代码:

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 完全陌生,希望您能帮助我找出错误或错误的语法。

【问题讨论】:

  • 在问题本身中发布相关代码。另外,您对装配的哪个部分有问题?
  • 好吧,我猜它是 while 循环,也许是堆栈
  • 您需要更加具体。堆栈有什么问题?您推送 2 个项目,然后将它们放入寄存器中。如果您要与0 进行比较,那么您会希望对0 有所减少。我在_while 的任何地方都看不到DEC。 :)
  • 好吧,我虽然在运行循环时 ecx 在某个时候得到 0
  • 我的 asm 有点生锈,但看起来你的 euclid 例程计算了答案,将其放入 eax,然后当它返回时,调用例程用 popa 破坏答案在任何地方使用或保存之前。

标签: assembly nasm greatest-common-divisor


【解决方案1】:

没有div ecx,ebx 指令。如果要执行ecx/ebx,则必须使用div r/m32 形式,它将edxeax 形成的64 位数量除以给定的操作数。因此,您必须注意将 edx 归零以获得 32 位被除数(或使用符号扩展 cdq 指令进行有符号操作)。 代码可能如下所示:

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

如有疑问,请使用instruction set reference

你的代码可能有逻辑错误,我只回答了你问的问题。

【讨论】:

    【解决方案2】:

    代码中的错误是您的逻辑。你应该返回'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
              }
    

    【讨论】:

      【解决方案3】:

      这是一个使用内联汇编计算最大公约数的程序。

      #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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多