Умножение/деление со сдвигом - Assembler
Формулировка задачи:
Помогите исправить код. Пожалуйста.
Операции умножения и деления выполнять с помощью операций сдвига.
F= y-(96*x)/16 (8-битные со знаком)
Ввод значений переменных организовать с клавиатуры.
Вывод результата организовать на экран. Если размер результата будет более 16 бит – результат преобразовывать в 16-битный
Листинг программы
- LOCALS
- .model small
- .stack 100h
- .data
- CrLf db 0Dh, 0Ah, '$'
- PromptGetX db 'Input X (-32768..+32767): ', '$'
- PromptGetY db 'Input Y (-32768..+32767): ', '$'
- KeyBuf db 7, 0, 8 dup(0) ;max,len,string,CR(0dh)
- msgError db 'Ошибка ввода числа', 0Dh, 0Ah, '$'
- X db ?
- Y db ?
- F db ?
- .code
- main proc
- mov ax, @data
- mov ds, ax
- @@GetX:
- ; ввод числа с клавиатуры (строки)
- lea dx, PromptGetX
- mov ah,09h
- int 21h
- mov ah, 0Ah
- mov dx, offset KeyBuf
- int 21h
- ; перевод строки (на новую строку)
- lea dx, CrLf
- mov ah,09h
- int 21h
- ; преобразование строки в число
- lea si, KeyBuf+1
- lea di, X
- call Str2Num
- ; проверка на ошибку
- jnc @@GetY
- ; если есть ошибка ввода - напечатать сообщение об ошибке
- lea dx, msgError
- mov ah,09h
- int 21h
- jmp @@GetX
- @@GetY:
- ; ввод числа с клавиатуры (строки)
- lea dx, PromptGetY
- mov ah,09h
- int 21h
- mov ah, 0Ah
- mov dx, offset KeyBuf
- int 21h
- ; перевод строки (на новую строку)
- lea dx, CrLf
- mov ah,09h
- int 21h
- ; преобразование строки в число
- lea si, KeyBuf+1
- lea di, Y
- call Str2Num
- ; проверка на ошибку
- jnc @@Calc
- ; если есть ошибка ввода - напечатать сообщение об ошибке
- lea dx, msgError
- mov ah,09h
- int 21h
- jmp @@GetY
- @@Calc:
- ;F= y-(96*x)/16 ???
- mov cl, X
- sal cl,1
- sal cl,1
- sal cl,1
- mov bh, Y
- sub bh,cl
- mov F, bh
- call Show_AX
- mov ax, 4C00h
- int 21h
- main endp
- ; выводит число из регистра AX на экран
- ; входные данные:
- ; ax - число для отображения
- Show_AX proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov cx, 10
- xor di, di ; di - кол. цифр в числе
- ; если число в ax отрицательное, то
- ;1) напечатать '-'
- ;2) сделать ax положительным
- or ax, ax
- jns @@Conv
- push ax
- mov dx, '-'
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- pop ax
- neg ax
- @@Conv:
- xor dx, dx
- div cx ; dl = num mod 10
- add dl, '0' ; перевод в символьный формат
- inc di
- push dx ; складываем в стэк
- or ax, ax
- jnz @@Conv
- ; выводим из стэка на экран
- @@Show:
- pop dx ; dl = очередной символ
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- dec di ; повторяем пока di<>0
- jnz @@Show
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Show_AX endp
- ; преобразования строки в число
- ; на входе:
- ; ds:[si] - строка с числом
- ; ds:[di] - адрес числа
- ; на выходе
- ; ds:[di] - число
- ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
- Str2Num proc
- push ax
- push bx
- push cx
- push dx
- push ds
- push es
- push si
- push ds
- pop es
- mov cl, ds:[si]
- xor ch, ch
- inc si
- mov bx, 10
- xor ax, ax
- ;если в строке первый символ '-'
- ; - перейти к следующему
- ; - уменьшить количество рассматриваемых символов
- cmp byte ptr [si], '-'
- jne @@Loop
- inc si
- dec cx
- @@Loop:
- mul bx ; умножаем ax на 10 ( dx:ax=ax*bx )
- mov [di], ax ; игнорируем старшее слово
- cmp dx, 0 ; проверяем, результат на переполнение
- jnz @@Error
- mov al, [si] ; Преобразуем следующий символ в число
- cmp al, '0'
- jb @@Error
- cmp al, '9'
- ja @@Error
- sub al, '0'
- xor ah, ah
- add ax, [di]
- jc @@Error ; Если сумма больше 65535
- cmp ax, 8000h
- ja @@Error
- inc si
- loop @@Loop
- pop si ;проверка на знак
- push si
- inc si
- cmp byte ptr [si], '-'
- jne @@Check ;если должно быть положительным
- neg ax ;если должно быть отрицательным
- jmp @@StoreRes
- @@Check: ;дополнительная проверка, когда при вводе положительного числа получили отрицательное
- or ax, ax ;
- js @@Error
- @@StoreRes: ;сохранить результат
- mov [di], ax
- clc
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- @@Error:
- xor ax, ax
- mov [di], ax
- stc
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Str2Num endp
- end main
Решение задачи: «Умножение/деление со сдвигом»
textual
Листинг программы
- LOCALS
- .model small
- .stack 100h
- .data
- CrLf db 0Dh, 0Ah, '$'
- PromptGetX db 'Input X
- : ', '$'
- PromptGetY db 'Input Y: ', '$'
- KeyBuf db 7, 0, 8 dup(0)
- ;max,len,string,CR(0dh)
- msgError db 'Ошибка ввода числа', 0Dh, 0Ah, '$'
- X db ?
- Y db ?
- F db ?
- .code
- main proc
- mov ax, @data
- mov ds, ax
- @@GetX:
- ; ввод числа с клавиатуры (строки)
- lea dx, PromptGetX
- mov ah,09h
- int 21h
- mov ah, 0Ah
- mov dx, offset KeyBuf
- int 21h
- ; перевод строки (на новую строку)
- lea dx, CrLf
- mov ah,09h
- int 21h
- ; преобразование строки в число
- lea si, KeyBuf+1
- lea di, X
- call Str2Num
- ; проверка на ошибку
- jnc @@GetY
- ; если есть ошибка ввода - напечатать сообщение об ошибке
- lea dx, msgError
- mov ah,09h
- int 21h
- jmp @@GetX
- @@GetY:
- ; ввод числа с клавиатуры (строки)
- lea dx, PromptGetY
- mov ah,09h
- int 21h
- mov ah, 0Ah
- mov dx, offset KeyBuf
- int 21h
- ; перевод строки (на новую строку)
- lea dx, CrLf
- mov ah,09h
- int 21h
- ; преобразование строки в число
- lea si, KeyBuf+1
- lea di, Y
- call Str2Num
- ; проверка на ошибку
- jnc @@Calc
- ; если есть ошибка ввода - напечатать сообщение об ошибке
- lea dx, msgError
- mov ah,09h
- int 21h
- jmp @@GetY
- @@Calc:
- mov ax, 0 ;bx:=96*X
- mov al, X
- mov cl, 5
- sal ax, cl
- mov bx, ax
- sal ax, 1
- add bx, ax
- mov cl, 4 ;bx:=(96*X)/16
- sar bx, cl
- mov bx, 9 ;ax:=Y
- mov al, Y
- sub ax, bx ;ax:=Y-(96*X)/16
- call Show_AX
- mov ax, 4C00h
- int 21h
- main endp
- ; выводит число из регистра AX на экран
- ; входные данные:
- ; ax - число для отображения
- Show_AX proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov cx, 10
- xor di, di ; di - кол. цифр в числе
- ; если число в ax отрицательное, то
- ;1) напечатать '-'
- ;2) сделать ax положительным
- or ax, ax
- jns @@Conv
- push ax
- mov dx, '-'
- mov ah, 2 ; ah - функция вывода символа на
- экран
- int 21h
- pop ax
- neg ax
- @@Conv:
- xor dx, dx
- div cx ; dl = num mod 10
- add dl, '0' ; перевод в символьный формат
- inc di
- push dx ; складываем в стэк
- or ax, ax
- jnz @@Conv
- ; выводим из стэка на экран
- @@Show:
- pop dx ; dl = очередной символ
- mov ah, 2 ; ah - функция вывода символа на
- экран
- int 21h
- dec di ; повторяем пока di<>0
- jnz @@Show
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Show_AX endp
- ; преобразования строки в число
- ; на входе:
- ; ds:[si] - строка с числом
- ; ds:[di] - адрес числа
- ; на выходе
- ; ds:[di] - число
- ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
- Str2Num proc
- push ax
- push bx
- push cx
- push dx
- push ds
- push es
- push si
- push ds
- pop es
- mov cl, ds:[si]
- xor ch, ch
- inc si
- mov bx, 10
- xor ax, ax
- ;если в строке первый символ '-'
- ; - перейти к следующему
- ; - уменьшить количество рассматриваемых символов
- cmp byte ptr [si], '-'
- jne @@Loop
- inc si
- dec cx
- @@Loop:
- mul bx ; умножаем ax на 10 ( dx:ax=ax*bx )
- mov [di], ax ; игнорируем старшее слово
- cmp dx, 0 ; проверяем, результат на переполнение
- jnz @@Error
- mov al, [si] ; Преобразуем следующий символ в число
- cmp al, '0'
- jb @@Error
- cmp al, '9'
- ja @@Error
- sub al, '0'
- xor ah, ah
- add ax, [di]
- jc @@Error ; Если сумма больше 65535
- cmp ax, 8000h
- ja @@Error
- inc si
- loop @@Loop
- pop si ;проверка на знак
- push si
- inc si
- cmp byte ptr [si], '-'
- jne @@Check ;если должно быть положительным
- neg ax ;если должно быть отрицательным
- jmp @@StoreRes
- @@Check: ;дополнительная проверка, когда при вводе
- положительного числа получили отрицательное
- or ax, ax ;
- js @@Error
- @@StoreRes: ;сохранить результат
- mov [di], ax
- clc
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- @@Error:
- xor ax, ax
- mov [di], ax
- stc
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Str2Num endp
- end main
Объяснение кода листинга программы
- Устанавливаются локальные переменные и параметры модели компоновки.
- Инициализируются переменные для вывода сообщений на экран и ввода/вывода данных.
- Определяется сообщение об ошибке.
- Инициализируются переменные для хранения вводимых значений X, Y и результата F.
- В процедуре main инициализируются стек и сегмент данных, инициализируются регистры.
- Происходит ввод значений X и Y с клавиатуры путем вызова соответствующих сообщений и обработки пользовательского ввода.
- Переводятся введенные строки в числа.
- Если произошла ошибка ввода, выводится сообщение об ошибке, и процесс ввода повторяется.
- Рассчитывается значение переменной F с использованием операций умножения, деления и арифметических операций.
- Результат выводится на экран с помощью процедуры Show_AX.
- Программа завершается системным вызовом.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д