#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
}