Как написать ассемблерную вставку на С++ для НОК четырех натуральных чисел?

274
11 февраля 2020, 15:00

День добрый! Вот моя задача:

Задано четыре натуральных числа. Реализуйте подпрограмму нахождения их наименьшего общего кратного. (реализовать как ассемблерную вставку С++)

#include <iostream>
using namespace std;
int nod(int a, int b) {
    int rez;
    a = a > 0 ? a : -a;
    b = b > 0 ? b : -b;
    if (a == 0)
        rez = b;
    else if (b == 0)
        rez = a;
    else if (a == b)
        rez = a;
    else if (a == 1 || b == 1)
        rez = 1;
    else {
        int ra = a % 2, rb = b % 2;
        if (!(ra || rb))
           rez = 2 * nod(a / 2, b / 2);
        else if (!ra)
           rez = nod(a / 2, b);
        else if (!rb)
           rez = nod(b / 2, a);
        else if (a > b)
           rez = nod(a - b, b);
        else
           rez = nod(b - a, a);
    }
    return rez;
}
int nok(int a, int b) {
    return a * b / nod(a, b);
}
int main() {
    int a, b, c, d;
    cout << "A, B, C, D\n";
    cin >> a >> b >> c >> d;
    cout << "NOK(A, B, C, D) = " << nok(nok(nok(a, b), c), d) << endl;
    _asm {
    .model small //tasm часть
    .data
    a dw 8
    b dw 12
    .code
    start :
    mov ax, @data
        mov ds, ax
        push a
        push b
        call lcm; //результат в ax
    xor ax, ax
        int 16h
        .exit
        x equ word ptr[bp + 6]
        y equ word ptr[bp + 4]
        gcd:
    push bp
        mov bp, sp
        sub sp, 12
        mov ax, x
        cmp ax, y
        jge @1
        mov ax, x
        mov bx, y
        mov x, bx
        mov y, ax
        @1:
        mov ax, x
        cwd
        mov bx, y
        idiv bx
        test dx, dx
        jne @2
        mov ax, y
        jmp @exit_gcd
        @2:
        push dx
        mov ax, y
        push ax
        call gcd
        @exit_gcd:
        mov sp, bp
        pop bp
        ret
        lcm :
    push bp
        mov bp, sp
        push x
        push y
        call gcd
        mov bx, ax
        mov ax, x
        imul y
        cwd
        idiv bx
        mov sp, bp
        pop bp
        ret
        end start
    }
}

Как переделать данную tasm-вставку под вставку ассемблера на C++ без .data и .model small? Проискал просторы Интернета - ничего по этому поводу не нашел.

Answer 1

Во-первых, тут 16 битный ассемблер для MS-DOS, который надо переделать в 32 битный. Для этого перед именами всех регистров нужно добавить E (push bp -> push ebp). Во-вторых, там в коде 2 функции для НОК и НОД, я решил ctrl+c, ctrl+v их в отдельные naked функции, в которые компилятор не добаляет никакой отсебятины. В gcd зачем-то резервируются 12 байт для локальных переменных, которых нет, я просто убрал эту строку. x equ word ptr[bp + 6] y equ word ptr[bp + 4] нужно тоже убрать. Еще пришлось переименовать некоторые метки, чтобы компиляотр не ругался. Получилось так:

#include <iostream>
using namespace std;

int __declspec(naked) gcd(int x, int y)
{
    __asm {
        push ebp
        mov ebp, esp
        mov eax, x
        cmp eax, y
        jge l1
        mov eax, x
        mov ebx, y
        mov x, ebx
        mov y, eax
        l1 :
        mov eax, x
        cwd
        mov ebx, y
        idiv ebx
        test edx, edx
        jne l2
        mov eax, y
        jmp exit_gcd
        l2 :
        push edx
        mov eax, y
        push eax
        call gcd
        exit_gcd :
        mov esp, ebp
        pop ebp
        ret
    }
}
int __declspec(naked) lcm(int x, int y)
{
    __asm {
        push ebp
        mov ebp, esp
        push x
        push y
        call gcd
        mov ebx, eax
        mov eax, x
        imul y
        cwd
        idiv ebx
        mov esp, ebp
        pop ebp
        ret
    }
}
int main() {
    int a, b, c, d;
    cout << "A, B, C, D\n";
    cin >> a >> b >> c >> d;
    cout << "NOK(A, B, C, D) = " << lcm(lcm(lcm(a, b), c), d) << endl;
}
READ ALSO
Разница между компиляторами c++1y и gnu c++ 11 4.9

Разница между компиляторами c++1y и gnu c++ 11 4.9

У меня запускается код с компилятором gnu++1y, но при использовании gnu c++ 11 49 выдает ошибку

284
Проверка форматирования кода

Проверка форматирования кода

Хочу организовать проверку форматирования кода на стороне ci с помощью clang-format и опции -output-replacements-xmlЗадумка была такая: если файл не отформатирован,...

275
Деструктор класса с полем структуры [закрыт]

Деструктор класса с полем структуры [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос, чтобы он соответствовал тематике «Stack Overflow на русском»

290
Дистрибутив linux для языков С, С++, Python

Дистрибутив linux для языков С, С++, Python

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

290