Консультация № 182937
25.04.2011, 17:30
51.37 руб.
0 17 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Необходимо написать небольшую программу, пример:
z=(x^2)-4y
Осуществить ручной ввод x,y. После этого изменить цвет фона и вывести z, при этом изменив цвет шрифта. Спасибо заранее :)

Обсуждение

Неизвестный
25.04.2011, 18:09
общий
Целые числа или вещественные? Во втором случае чуть-чуть посложнее ввод-вывод.
Да! И модель памяти? Или еще какие особые требования ...
Неизвестный
25.04.2011, 18:26
общий
Целые числа, модель памяти (tiny, small)Больше не каких
Неизвестный
25.04.2011, 18:27
общий
код хорошо бы поменьше сделать :)
Неизвестный
26.04.2011, 02:08
общий
26.04.2011, 18:07
Вы не указали ОС (линукс, DOS, ...). И синтаксис языка, на котором вам нужна эта программа.
Вот ваша задача на fasm под win x64:
x, y - целые, без знаковые числа, по 16 десятичных разрядов
z -целое, знаковое, 32десятичных разряда
[code h=200]
format PE64 GUI 5.0
entry start

include '%fasminc%\win64a.inc'

section '.text' code readable executable

start:
sub rsp,8

invoke GetModuleHandle,0
mov [wc.hInstance],rax
invoke LoadIcon,0,IDI_APPLICATION
mov [wc.hIcon],rax
mov [wc.hIconSm],rax
invoke LoadCursor,0,IDC_ARROW
mov [wc.hCursor],rax
invoke RegisterClassEx,wc
test rax,rax
jz error

invoke CreateWindowEx,WS_EX_CONTROLPARENT,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,100h,100h,130h,58h,0,0,[wc.hInstance],0
test rax,rax
jz error

msg_loop:
invoke GetMessage,msg,NULL,0,0
cmp eax,1
jb end_loop
jne msg_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp msg_loop

error:
invoke MessageBox,0,_error,0,MB_ICONERROR+MB_OK

end_loop:
invoke ExitProcess,[msg.wParam]

proc WindowProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam
mov [hwnd],rcx
mov [wmsg],rdx
mov [wparam],r8
mov [lparam],r9

cmp edx,WM_DESTROY
je _wmdestroy
cmp edx,WM_CREATE
je _wmcreate
cmp edx,WM_COMMAND
je _wmcommand
_defwndproc:
invoke DefWindowProc,rcx,rdx,r8,r9
jmp _finish
_wmcreate:
invoke CreateWindowEx,0,_clasedit,0,WS_VISIBLE or WS_CHILD or ES_RIGHT or ES_NUMBER,4,4,80h,10h,[hwnd],0,[wc.hInstance],0
mov [hwnd_x],rax
invoke CreateWindowEx,0,_classstatic,_title1,WS_VISIBLE or WS_CHILD,86h,4,20h,10h,[hwnd],0,[wc.hInstance],0
invoke CreateWindowEx,0,_clasedit,0,WS_VISIBLE or WS_CHILD or ES_NUMBER,0A6h,4,80h,10h,[hwnd],0,[wc.hInstance],0
mov [hwnd_y],rax
invoke CreateWindowEx,0,_classstatic,_title2,WS_VISIBLE or WS_CHILD or SS_CENTER,4,20h,120h,10h,[hwnd],0,[wc.hInstance],0
mov [hwnd_z],rax
invoke GetDC,rax
mov [_int_z],rax
jmp _finish
_wmcommand:
cmp r9,[hwnd_y]
jz @F
cmp r9,[hwnd_x]
jnz _finish
@@:
mov qword[text_x],0
mov qword[text_y],0
mov qword[text_x+8],0
mov qword[text_y+8],0
invoke GetWindowText,[hwnd_x],text_x,11h
mov [len_x],eax
invoke GetWindowText,[hwnd_y],text_y,11h
mov [len_y],eax
xor ebx,ebx
xor eax,eax
xor ecx,ecx
cikl_x:
imul rbx,0Ah
mov al,byte[text_x+rcx]
and al,0Fh
add rbx,rax
inc ecx
cmp ecx,[len_x]
jl cikl_x
mov rax,rbx
mul rbx
mov r8,rax
mov r9,rdx

xor ebx,ebx
xor eax,eax
xor ecx,ecx
cikl_y:
imul rbx,0Ah
mov al,byte[text_y+rcx]
and al,0Fh
add rbx,rax
inc ecx
cmp ecx,[len_y]
jl cikl_y
shl rbx,2
sub r8,rbx
jnc @F
neg r8
dec r9
jns @F
inc r9
mov byte[_title2+1],'-'
@@:
std
mov rdi,_title2+21h
mov ecx,20h
;mov r8,rax
mov ebx,0Ah
mov rax,r9
_div:
xor edx,edx
div rbx
mov r9,rax
mov rax,r8
div rbx
mov r8,rax
mov al,dl
or al,30h
stosb
mov rax,r9
loop _div
mov al,30h
dec ecx
cld
inc rdi
rep scasb
dec rdi
mov rsi,rdi
mov rdi,_title2+2

_clea_zero:
movsb
cmp rsi,_title2+22h
jl _clea_zero
@@:
xor eax,eax
stosb
invoke SetWindowText,[hwnd_z],_title2
mov qword[_title2],'= '
jmp _finish
_wmdestroy:
invoke PostQuitMessage,0
xor eax,eax
_finish:
ret
endp

section '.data' data readable writeable

_title TCHAR 'z=(x^2)-4y',0
_title1 TCHAR '^2-4*',0
_title2 TCHAR '= ',0
rb 22h
_class TCHAR 'FASMWIN64',0
_clasedit TCHAR 'EDIT',0
_classstatic TCHAR 'STATIC',0
_error TCHAR 'Startup failed.',0

wc WNDCLASSEX sizeof.WNDCLASSEX,0,WindowProc,0,0,0,0,0,COLOR_BTNFACE+1,0,_class,0

msg MSG

section '.idata' import data readable writeable

library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL'

include '%fasminc%\api\kernel32.inc'
include '%fasminc%\api\user32.inc'

section 'noinit' data readable writeable
len_x dd ?
len_y dd ?
hwnd_x dq ?
hwnd_y dq ?
hwnd_z dq ?
_int_z dq ?
text_x rw 10h
text_y rw 10h
[/code]

Могу под x86 написать, только это посложнее будет
Неизвестный
26.04.2011, 07:48
общий
ой, извините пожалуйста, tasm (dos)
давно
Посетитель
7438
7205
26.04.2011, 13:11
общий
26.04.2011, 14:10
Если модель память tiny, то явно речь идет о ДОС.
Вы не находите?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.04.2011, 14:03
общий
Адресаты:

Когда я прочитал задание, этого ещо не было.
давно
Посетитель
7438
7205
26.04.2011, 15:10
общий
это ответ
Здравствуйте, JohnyWayne!
Чтобы использовать цвет символов, использован прямой вывод в видеопамять.
Чтобы ограничить работу с одним словом, в программе введено ограничение (полагаю, это непринципиально ):
число должно быть по модулю <= 179. (т.к. это максимальное число, когда 1792 - 4[$149$](-179) [$8804$] 32767, где 32767 - максимальное знаковое число, помещающееся в слово)
[code h=200]
.model tiny

Attr_white_on_black equ 07h ;основной цвет (белый по черному)
Attr_yellow_on_red equ 2eh ;цвет Z (желтый по красному)
MAX_NUM equ 179 ;максимальное значение чисел X и Y

.data
x dw 0
y dw 0
sEnterX db 'Enter X: ',0
sEnterY db 'Enter Y: ',0
sZ db 'Z = ',0
sAny db 'Press any key',0
sBuffer db 16 dup (?)

.code ;сегмент кода
org 100h ;начальный адрес для СОМ-программы
start:
mov ax, 0003h ;необходимо под XP для прямого вывода в видеопамять
int 10h

mov cx, 2000h ;спрячем курсор
mov ah, 1
int 10h

mov ax, 0b800h
mov es, ax ;сегмент видеопамяти

xor di, di ;первая колонка первой строки
lea si, sEnterX ;приглашение для ввода X
call EnterNum ;введем число в AX
mov x, ax ;x = AX

mov di, 80*2 ;первая колонка второй строки
lea si, sEnterY ;приглашение для ввода Y
call EnterNum ;введем число в AX
sal ax, 1 ;умножим на 2!
sal ax, 1 ;умножим на 4!
mov y, ax ;y = AX*4

mov di, 80*2*2 ;первая колонка третьей строки
lea si, sZ ;адрес строки 'Z = '
mov ah, Attr_white_on_black ;атрибут
call PrintStr ;выведем

mov ax, x
imul x
sub ax, y ;ax = x^2 - y*4

lea si, sBuffer ;адрес буфера
call ConvertToStr ;преобразуем в строку

mov ah, Attr_yellow_on_red ;желтый по красному
lea si, sBuffer ;строка-число
call PrintStr ;выведем

mov di, 80*3*2 ;четвертая строка
lea si, sAny ;Press any key
mov ah, Attr_white_on_black ;белый по черному
call PrintStr ;выведем

mov ah, 0
int 16h ;ждем any key

mov ax, 0003h
int 10h ;чтобы очистить экран

mov ax, 4c00h
int 21h ;выход в ДОС

;вывод строки [ds:si], заканчивающейся 0, в видеопамять [es:di], аттрибут в ah
PrintStr proc
lodsb
cmp al, 0
je PrintRet ;конец строки?
stosw
jmp PrintStr
PrintRet:
ret
PrintStr endp

;ввод строки с анализом на цифры, знак минус и на переполнение
EnterNum proc
;выведем приглашение
mov ah, Attr_white_on_black ;белым по черному
call PrintStr ;выведем

xor bx, bx ;здесь будет число
mov bp, 1 ;признак знака, 1 : >0, (-1) : <0
mov cx, 10 ;будем умножать на 10
EnterLoop:
mov ah, 0 ;ждем код
int 16h
cmp al, 0dh ;Enter - выход
je EnterRet
cmp al, '-' ;минус?
jne EnterDigit ;нет - на проверку на цифру
cmp bp, 1 ;минус уже был?
jnz EnterLoop ;был - игнорируем
stosb ;выводим на экран
inc di ;со старым аттрибутом (там 07)
neg bp ;(-1) - отрицательное число
jmp EnterLoop ;вводим дальше

EnterDigit: ;проверяем на цифры
sub al, '0' ;превратим в число 0-9
jc EnterLoop ;меньше '0' - игнорируем
cmp al, 9 ;больше '9'
ja EnterLoop ; тоже игнорируем
mov ah, 0 ;делаем слово
mov si, bx ;сохраним старое слово
xchg ax, bx ;ax = старшим разрядам, bx = введенному мл разряду
imul cx ;ax = ст разр, сдвинутым на 1 десятичный разряд
add ax, bx ;сложим с младшим
cmp ax, MAX_NUM ;сравним с максимальным
jbe DigitOk ;<= - продолжаем
mov bx, si ;восстановим старое
jmp EnterLoop ;т.о., игнорируем
DigitOk: ;все отлично, выведем введенный разряд
xchg ax, bx ;ax = младшему разряду
add al, '0' ;делаем символ '0'-'9'
stosb ;выводим
inc di ;со старым аттрибутом
jmp EnterLoop ;продолжаем
EnterRet:
mov ax, bx ;введенное число
imul bp ;умножим на +-1, чтобы учесть знак
ret
EnterNum endp

;преобразование знакового числа из ax в строку [ds:si]
ConvertToStr proc
test ax, ax ;проверим на знак
jns form_str ;для положительного на вывод
push ax ;для отрицательного выводим - и меняем знак
mov al,'-' ;знак -
mov [si], al ;сохраним
inc si ;сдвигаем указатель
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 ;продолжим

pr_loop: ;цикл вывода десятичных цифр-символов
pop ax ;востановим очередной разряд (от старшего к младшему)
add al, '0' ; символ цифры
mov [si], al ;сохраняем
inc si
loop pr_loop ; по всем цифрам
mov byte ptr [si],0 ;закроем строку 0
ret
ConvertToStr endp

end start
[/code]
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.04.2011, 17:12
общий
mov di, 80*2 ;первая колонка второй строки
lea si, sEnterY ;приглашение для ввода Y
call EnterNum ;введем число в AX
sal ax, 2 ;умножим на 4!
mov y, ax
Выдает ошибку на mov di, 80*2
Rotate count out of range
давно
Посетитель
7438
7205
26.04.2011, 17:16
общий
Чем ассемблируете?
Напишите, в конце концов, mov di, 160
Аналогично, в других местах
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.04.2011, 17:20
общий
хм не помогаетtasm ругается все равно
давно
Посетитель
7438
7205
26.04.2011, 17:26
общий
Тогда "залейте" свой исходник на сервер в "мои файлы" и дайте ссылку.
Гляну, что там у Вас получается...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.04.2011, 17:32
общий
прикрепил
Прикрепленные файлы:
d3310dc116b5a240a88ee4bfeba7bc8f.rar
давно
Посетитель
7438
7205
26.04.2011, 17:45
общий
Все понятно
Проблема не в mov di, 80*2 (можете вернуть, как было)
А в sal ax,2.
Дело в том, что для процессора 86-го, а именно он считается заданным, если не указано что-то другое, данная команда не работает.
Можно только sal ax,1 или sal ax,cl
Некоторые ассемблеры (мой tasm 4.1, например) данную проблему обходят, задавая автоматом несколько команд sal ax,1
Ваш же, версии 2.0, этого не делает...
Короче, запишите вместо указанной команды две sal ax,1 и все пойдет
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.04.2011, 17:48
общий
спасибо большое, все заработало)
давно
Старший Модератор
31795
6196
27.04.2011, 14:12
общий
Адресаты:

Странно, но из всех новых команд 186-го процессора:
Цитата: вики
В процессорах семейства i186 был расширен набор команд. Были добавлены дополнительные команды работы со стеком (PUSHA, POPA PUSH), с портами ввода-вывода (INS, OUTS), арифметические команды (IMUL, ROL/ROR, RCL/RCR, SAL/SAR, SHL/SHR с непосредственно указанным числом бит сдвига) и команды реализации языков высокого уровня (ENTER, LEAVE, BOUND).

Т4.1 не раегирует именно на выделеные команды, остальные команды определяются как не соответсвующие выбраному процессору.

Т2.0 четко реагирует на них.

Скорее всего, Т2.0, выпуска 1990 года, в то время было слишком много РС с различными процессорами семейства х86+ и такая строгость к коду была необходима. Т4.1 выпуска 1996 года, уже существенно увеличилось количество х286 процессоров и соответсвенно разработчики решили, что эти команды можно отнести к процессору х86, для уменьшения размера кода.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
27.04.2011, 14:33
общий
Адресаты:
Ничего странного... Просто в Borland-е посчитали, что указанные команды легко заменить на эквивалентную последовательность соответствующих команд. С другими же не захотели связываться.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа