Проблема с преобразованием C в MASM: поиск уникальных простых множителей и дружественных пар

#c #assembly #visual-c #x86 #masm

# #c #сборка #visual-c #x86 #masm

Вопрос:

У меня есть задание в моем классе компьютерной архитектуры и языка ассемблера, где я получил следующий код на C , и меня попросили преобразовать его часть в код сборки MASM:

 #include <iostream>
#include <ctime>
using namespace std;

#define MAXIMUM 1000000

int Factors[MAXIMUM];
int properFactors(int, int[], intamp;);

int main()
{
    int q;
    int numFactors;
    int pairCount = 0;

    clock_t startClock = clock();
    for (int p = 1; p <= MAXIMUM; p  )
    {
        q = properFactors(p, Factors, numFactors);

        if (q > p)
        {
            if (properFactors(q, Factors, numFactors) == p)
            {
                cout << "Amicable Pair: " << p << ", " << q;
                cout << "(" << q << " has " << numFactors << " factors : ";
                cout << Factors[0];
                for (int i = 1; i < numFactors; i  ) 
                    cout << ", " << Factors[i];
                cout << ")" << endl;
                pairCount  ;
            }
        }
    }

    double totalTime = (double)(clock() - startClock) / CLOCKS_PER_SEC;
    cout << "Number of amicable pairs found = " << pairCount << endl;
    cout << "Time = " << totalTime << " seconds" << endl;
}

int properFactors(int n, int factors[], intamp; numFactors)
{
    int i, k, sum, factor2;
    i = 1;
    k = 2;
    sum = 1;
    factors[0] = 1;

    while (k * k <= n) {
         if (n % k == 0) {
              sum = sum   k;
              factors[i] = k;
              i  ;

              factor2 = n / k;
              if (factor2 != k) {
                   sum = sum   factor2;
                   factors[i] = factor2;
                   i  ;
              }
           }
        k  ;
     }

    numFactors = i;
    return sum;
}
 

Часть, которую я должен преобразовать в сборку, — это следующая часть из соответствующей функции factors:

     i = 1;
    k = 2;
    sum = 1;
    factors[0] = 1;

    while (k * k <= n) {
         if (n % k == 0) {
              sum = sum   k;
              factors[i] = k;
              i  ;

              factor2 = n / k;
              if (factor2 != k) {
                   sum = sum   factor2;
                   factors[i] = factor2;
                   i  ;
              }
           }
        k  ;
     }
 

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

 __asm {
        mov eax, 1                              ; i = 1;
        mov i, eax
        mov eax, i

        mov ebx, 2                              ; k = 2;
        mov k, ebx                          
        mov ebx, 1                              ; sum = 1;
        mov sum, ebx
        
        mov ebx, factors
        mov esi, 0
        mov [ebx   4 * esi], 1                  ; factors[0] = 1;

        while_1:                                ; while (k * k <= n) {
            mov ecx, k
            imul ecx, k
            cmp ecx, n
            jle while_1_begin
            jmp while_1_end

        while_1_begin: 

            if_1:                               ; if (n % k == 0) {
                mov edx, n
                cdq
                idiv k
                cmp edx, 0
                je if_1_begin
                jmp if_1_end

            if_1_begin:
                mov esi, sum                    ; sum = sum   k;
                add esi, k
                mov sum, esi

                mov esi, k
                mov [ebx 4*eax], esi            ; factors[i] = k;
                inc i                           ; i  ;
                mov eax, i

                mov esi, n
                cdq 
                idiv k
                mov factor2, esi                ; factor2 = n / k;

                mov esi, k

                if_2:                           ; if (factor2 != k) {
                    cmp factor2, esi
                    jne if_2_begin
                    jmp if_2_end

                if_2_begin:
                    mov edi, sum                ; sum = sum   factor2;
                    add edi, factor2
                    mov sum, edi

                    mov edi, factor2

                    mov eax, i
                    mov [ebx 4*eax], edi        ; factors[i] = factor2;
                    inc i                       ; i  ;
                    mov eax, i

                    jmp if_2_end

                if_2_end:                       ; }

                jmp if_1_end

            if_1_end:                           ; }

            inc k                               ; k  ;

            jmp while_1

        while_1_end:                            ; }
        
        mov i, eax
    }
 

Кто-нибудь может помочь мне понять, почему моя программа работает некорректно?

Комментарии:

1. Выполните это с помощью отладчика Visual Studio.

2. Почему вы делаете cdq это сразу после mov edx, n этого ? Почему вы думаете , что eax это будет i mov [ebx 4*eax], esi сделано ?

Ответ №1:

Похоже, вы ожидаете, что деление idiv будет продолжено EDX:ESI , оставив его частное в ESI и остаток в EDX . Это неправильно! Деление idiv делится EDX:EAX на его операнд и оставляет частное в EAX , а остаток в EDX .

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

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

 __asm {
        mov  EAX, 2                             ; k = 2;
        mov  k, EAX                          

        DEC  EAX                                ; i = 1;
        mov  i, eax

        mov  sum, EAX                           ; sum = 1;
        
        mov  ebx, factors
        mov  [EBX], EAX                         ; factors[0] = 1;

        while_1:                                ; while (k * k <= n) {
            mov  ecx, k
            imul ecx, ECX
            cmp  ecx, n
            JG   while_1_end

            if_1:                               ; if (n % k == 0) {
                mov  EAX, n
                cdq
                idiv k
                TEST EDX, EDX
                JNZ  if_1_end

                mov  esi, sum                   ; sum = sum   k;
                add  esi, k
                mov  sum, esi

                MOV  EAX, i
                mov  esi, k
                mov  [ebx 4*eax], esi           ; factors[i] = k;
                inc  i                          ; i  ;
                
                mov  EAX, n
                cdq 
                idiv k
                mov  factor2, EAX               ; factor2 = n / k;

                if_2:                           ; if (factor2 != k) {
                    cmp  EAX, K
                    JE   if_2_end

                    ADD  sum, EAX               ; sum = sum   factor2;

                    mov  ESI, i                 ; factors[i] = factor2;
                    mov  [ebx 4*ESI], EAX
                    inc  i                      ; i  ;

                if_2_end:                       ; }

            if_1_end:                           ; }

            inc  k                              ; k  ;

            jmp  while_1

        while_1_end:                            ; }
        
        mov  i, eax
    }