Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для Windows/Dos > Вычислить арифметическое выражение


Автор: hack7 24.8.2017, 15:58
Здравствуйте! Проверьте что не так надо вычислить выражение f = (a-b)*c/2+d, если a, b, c, d - байтовые, a=15, b = 70, c=25, d=35 Надо еще вывести результат в виде двоичном и шестнадцатеричном значении. 

.model small
.stack 256
.data
a db 15
b db 70
c db 25
d db 35
f dw 0
.code
main:
xor ax, ax
mov al, 15
cbw
movsx bx, ax
sub ax, bx
imul c
idiv 2
xor dx, dx
mov dl, d
movsx ax, dx
add ax, dx
exit:
mov ax, 4c00h
int 21h
end main

Автор: JAPH 27.8.2017, 10:15
Проследите внимательно за тем, как исполняются команды.

Код
        .model  small
        .stack  256
        .data
a       db      15
b       db      70
c       db      25
d       db      35
f       dw      0
        .code
main:   xor     ax, ax     ; Лишняя команда, т.к. дальше все равно AX перезаписывается
        mov     al, 15     ; Следите за тем, что получается. Вот сейчас AL = 15. Наверное, нужно было не хардкодить константу, а прочитать ячейку а
        cbw                ; Теперь AX = 15
        movsx   bx, ax     ; Знаковое расширение 16-битного AX до 16-битного же BX? Такой команды нет, просто MOV тогда. Ну да ладно, BX = 15
        sub     ax, bx     ; AX := AX - BX, т.е. теперь AX = 0. Вы же хотели a-b, т.е. в BX должно было быть b, а не AX? Предыдущая команда неверна
        imul    c          ; Умножает AL на c и помещает результат в AX. Зачем было раньше работать с 16-битными числами, если здесь AH игнорируется?
        idiv    2          ; Такой команды тоже нет. IDIV принимает либо регистр, либо ячейку памяти в качестве операнда.
        xor     dx, dx     ; DX = 0
        mov     dl, d      ; DL = d, но DX это не знаковое расширение DL сейчас. Можно было сделать MOVSX DX, d
        movsx   ax, dx     ; AX = d с поправкой на то, что должно быть просто MOV
        add     ax, dx     ; AX := AX + DX, т.е. AX = 2d. Та же ошибка, что и с вычитанием
exit:   mov     ax, 4C00h
        int     21h
        end     main


Вычитание a-b делайте 8-битным. Далее умножение дает 16-битное число. Деление надо тоже сделать 16-битным, т.к. результат, скорее всего, не поместится в 8 бит. Поэтому надо делитель 2 занести либо в регистр, либо в ячейку памяти, и использовать idiv с 16-битным операндом, которая делит на него 32-битное число в регистровой паре DX:AX, которое нужно получить из AX командой cwd. Зачем нужна f, я не понял. По поводу вывода чисел смотрите статью http://forum.vingrad.ru/faq/topic-158522/kw-%D0%B2%D0%B2%D0%BE%D0%B4-%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4-%D1%87%D0%B8%D1%81%D0%BB%D0%B0.html

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)