Консультация № 182856
14.04.2011, 19:25
52.03 руб.
0 4 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Прошу помочь составить макрос к https://rfpro.ru/question/182640 Заранее Спасибо :)

Обсуждение

давно
Старший Модератор
31795
6196
14.04.2011, 19:38
общий
Какой имено участок кода Вы хотите заключить в макрос?
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
14.04.2011, 19:45
общий
ввод x, ввод y... вообщем все основные участки
давно
Посетитель
7438
7205
14.04.2011, 19:59
общий
это ответ
Здравствуйте, JohnyWayne!
Да, пожалуйста...
Например, так:
[code h=200];z = x^2 / y-2, если y<2, x<0
; = y - x, если y > x
; = -48h, в остальных случаях
;Необходимо написать программу на Ассемблере,
;которая просит ввод значений x и y, решает пример,
;и выводит ответ т.е. z.

GET_NUM MACRO STRING
local CetNumStart
CetNumStart:
lea dx, STRING ; строка приглашения
call GetNum ; введем число в AX
jc CetNumStart ; повторим, если ошибка
endm

CALC_Z MACRO X, Y
LOCAL Cmp_Second, Set_Third, Out_Z
mov ax, Y
mov bx, X
cmp ax, bx ;Y < X ?
jle Cmp_Second ;нет -> сравниваем дальше
sub ax, bx ;да -> Z = Y - X
jmp Out_Z ;на вывод результата

Cmp_Second: ;вторая проверка
cmp ax, 2 ;Y < 2 ?
jge Set_Third ;нет -> на остальные случаи
test bx, bx ;X < 0 ?
jge Set_Third ;нет -> на остальные случаи

xchg ax, bx ;AX = X, BX = Y
mul ax ;DX:AX = X^2
sub bx, 2 ;BX = Y - 2
cwd ;подготовимся к делению
idiv bx ;AX = DX:AX / BX
jmp Out_z ;на вывод

Set_Third:
mov ax, -48h ;все остальные случаи

Out_Z: ;вывод результата
ENDM

.model small
.stack 100h
.data

;строки сообщений
sGetX db 0dh,0ah,'Enter X: $'
sGetY db 0dh,0ah,'Enter Y: $'
sOutZ db 0dh,0ah,'Z = $'
sAny db 0dh,0ah,'Press any key$'

buf label byte ; буфер для приема строки с клавиатуры (по ф-и 0ah)
max db 20 ; максимальная длина строки
len db 0 ; реальная длина введенной строки
string db 20 dup (?) ; сама строка

.code
start:
mov ax, @data
mov ds, ax
mov es, ax

GET_NUM sGetX
mov bx, ax ; сохраним в BX = X

GET_NUM sGetY

CALC_Z bx, ax

lea dx, sOutZ ; строка Z =
call PrintNum ; выведем знаковое число Z

lea dx, sAny ;выведем 'Press any key'
mov ah, 9
int 21h

mov ah, 0 ; ждем нажатие на клавишу
int 16h

mov ax,4c00h ; конец работы
int 21h

PrintNum proc ; вывод знакового числа из AX
push ax
mov ah, 9
int 21h ; вывод строки (из DX)
pop ax

test ax, ax ;проверим на знак
jns form_str ;для положительного на вывод
push ax ;для отрицательного выводим - и меняем знак
mov dl,'-' ;знак -
mov ah, 2
int 21h
pop ax
neg ax ;меняем знак числа на +, теперь оно положительное

form_str:
mov bx, 10 ; будем делить на 10
xor cx, cx ; счетчик цифр
div_loop: ; цикл получения десятичных разрядов
xor dx, dx ; подготовимся для очередного деления
div bx ; в dx остаток - очередной десятичный разряд
push dx ; сохраним в стеке (от младшего к старшему)
inc cx ; посчитаем
test ax, ax ; есть еще десятичные разряды?
jnz div_loop ; продолжим

mov ah, 2
pr_loop: ; цикл вывода десятичных цифр-символов
pop dx ; востановим очередной разряд (от старшего к младшему)
add dl, '0' ; символ цифры
int 21h ; вывод
loop pr_loop ; по всем цифрам

ret
PrintNum endp
;
GetNum proc ; преобразование сроки в число
push bx
mov ah, 9
int 21h ; приглашение ввести строку
lea dx, buf
mov ah, 0ah
int 21h ; вводим строку

xor di, di ; здесь будем накапливать число
mov cl, 0 ; флаг знака
mov ch, 0 ; количество цифр
xor bx, bx ; очередной знак (для сложения со словом)
lea si, string ; числовая строка
get_num_loop:
lodsb ; очередная цифра
; проверим на разделители
cmp al, 0dh
je num_end_found ; конец ввода
cmp al, ' '
je num_end_found
cmp al, 9
je num_end_found
; минус может быть олько один и в первой позиции!
cmp al, '-'
jne cmp_num ; на проверку цифр
test ch, ch ; были ли введены цифры?
jnz set_c ; были - ошибка - минус не в первой позиции!
test cl, cl ; был ли уже введен минус?
jnz set_c ; был - ошибка - можно только один!
mov cl, 1 ; пометим отрицательное число
jmp get_num_loop ; на анализ следующего символа
cmp_num:
cmp al, '0' ; цифра?
jb set_c ; ошибка - не цифра!
cmp al, '9'
ja set_c

inc ch ; считаем цифры
and al, 0fh ; цифра -> число (30h-39h -> 0-9)
mov bl, al ; сохраним (bh=0)
mov ax, 10 ; умножим на 10
imul di ; предыдущее значение
test dx, dx ; больше cлова - ошибка!
jnz set_c
add ax, bx ; добавим сохраненный разряд
jc set_c ; больше слова - ошибка!
js set_c ; больше 32767 - ошибка!
mov di, ax ; сохраним
jmp get_num_loop ; на анализ следующего символа

num_end_found: ; встретили разделитель
test ch, ch ; что-то было?
jz set_c ; не было числа (например, был введен один минус)
test cl, cl ; число отрицательное?
jz get_num_ret
neg di ; дополнительный код отрицательного числа
get_num_ret:
mov ax, di ; результат в ax
pop bx
clc ; все ок
ret
set_c:
pop bx
stc ; ошибка
ret
GetNum endp

end start
[/code]
5
Спасибо большое! Сейчас буду разбирать принципы :)
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
14.04.2011, 20:05
общий
Чуток добавил...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа