Задача стоит такая: При запуске появляется консоль, куда вводятся параметры. После этого консоль закрывается и появляется винапишное окно. Возможно ли это? Желательно с примером. Просто преподавателю необходимо продемонстрировать умение работы с прерываниями (т.е. консоль), а окошко нужно чтобы рисовать туда очень сложные художества. Собственно окно только для рисования нужно.
Консоль всеголишь текстовое окно которое csrss принадлежит и к ядру, темболее к прерываниям никакого отношения не имеет. Консольное - это обычное приложение.
в 1.asm работа с прерываниями, туда нужно интегрировать окно, которое будет вызываться после ввода параметров. Код с окном примерно такой Код (Text): format PE GUI include 'win32ax.inc' start: xor ebx,ebx mov edi,wTitle mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,window_procedure,ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW+1,ebx,edi ; +--------------------------+ ; | creating the main window | ; +--------------------------+ push ebx push esi push ebx push ebx shl esi,9 invoke CreateWindowEx,ebx,edi,edi,\ WS_OVERLAPPEDWINDOW+WS_VISIBLE+WS_OVERLAPPED,\ esi,esi,800,600 mov ebp,esp ;+---------------------------+ ;| entering the message loop | ;+---------------------------+ window_message_loop_start: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp window_message_loop_start ;+----------------------+ ;| the window procedure | ;+----------------------+ window_procedure: hWnd equ ebp+8 uMsg equ ebp+0xC enter sizeof.PAINTSTRUCT,0 mov eax,[uMsg] mov edi,[hWnd] dec eax dec eax; cmp uMsg,WM_DESTROY je wmDESTROY sub eax,WM_PAINT-WM_DESTROY; cmp uMsg,WM_PAINT je wmPAINT leave jmp dword [DefWindowProc] wmDESTROY: invoke ExitProcess,ebx wmPAINT: invoke BeginPaint,edi,esp invoke Arc,dword[esp+32],50,80,519,220,69,122,64,174 invoke MoveToEx,dword[esp+12],69,122,ebx invoke LineTo,dword[esp+8],130,78 invoke LineTo,dword[esp+8],248,4 invoke MoveToEx,dword[esp+12],64,174,ebx invoke LineTo,dword[esp+8],121,215 invoke LineTo,dword[esp+8],250,297 invoke MoveToEx,dword[esp+12],20,20,ebx invoke LineTo,dword[esp+8],130,78 invoke EndPaint,edi,esp a1: leave retn 0x10 wTitle db 'Мустафин ММ-494 F.Аппроксимация',0 data import library KERNEL32, 'KERNEL32.DLL',\ USER32, 'USER32.DLL',\ GDI32, 'GDI32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import USER32,\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ BeginPaint, 'BeginPaint',\ EndPaint, 'EndPaint' import GDI32,\ Arc, 'Arc',\ MoveToEx, 'MoveToEx',\ LineTo, 'LineTo' end data В общем эти две части нужно совместить, чтобы сначала ввод - потом окно.
Извиняюсь, не прикрепил Код (Text): ;============================================================== ;============== Задача F.Аппроксимация ======================== ;============================================================== data segment pkey db "press any key...$" winput db "wrong input...$" count dw ? ;переменная - кол-во измерений array dw 100 dup (0) ;массив измерений x dw 100 dup (0) ;массив абсцисс кривой y dw 100 dup (0) ;массив ординат кривой endl db 0dh,0ah,'$' ;перевод на другую строку x1 dw 0 x2 dw 0 y1 dw 0 y2 dw 0 min dw 0 max dw 0 min_calc dw 0 max_calc dw 0 index dw 0 value dw 0 ends stack segment dw 128 dup(0) ends code segment start: ; set segment registers: mov ax, data mov ds, ax mov es, ax ;------------------------------------------------------------- ; ввод начальных параметров ;------------------------------------------------------------- ;mov min,-5 ;mov max,5 ;mov min_calc,-3 ;mov max_calc,6 ;call AddIntervals ;ввод числа измерений call ReadInteger mov count,ax mov bx,count ;проверка значения числа измерений (д.б. от 2 до 40) cmp count,2 jbe wrong_input cmp count,40 jae wrong_input ;переход на новую строку mov ah,09h lea dx,endl int 21h ;ввод массива измерений call ReadArray ;переход на новую строку mov ah,09h lea dx,endl int 21h call GetLines ;------------------------------------------------------------- ;выход и обработка ошибок ;------------------------------------------------------------- ;завершение работы exit: lea dx, pkey mov ah, 9 int 21h ;output string at ds:dx mov ah, 1 ;wait for any key.... int 21h mov ax, 4c00h ;exit to operating system. int 21h ;при ошибке ввода выводим сообщение и завершаем работу wrong_input: lea dx, winput mov ah, 9 int 21h ; output string at ds:dx jmp exit ;============================================================== ;============ Процедуры ====================================== ;============================================================== ;------------------------------------------------------------- ;ВВОД ДЕСЯТИЧНОГО ЧИСЛА В AX ;------------------------------------------------------------- ReadInteger proc push cx ; сохранение регистров push bx push dx xor cx, cx mov bx, 10 call ReadChar ; ввод первого символа cmp al,'-' ; если минус - ошибка ввода je wrong_input jmp not_minus read: call ReadChar ; ввод очередного символа not_minus: cmp al, 13 ; Enter ? je done ; да - > завершение sub al, '0' ; нет -> перевод цифры char -> int xor ah, ah xor dx, dx xchg cx, ax mul bx add ax, cx xchg ax, cx jmp read done: xchg ax, cx pop dx pop bx pop cx ret ReadInteger endp ;------------------------------------------------------------- ;ВВОД МАССИВА ЧИСЕЛ (РАЗДЕЛЕННЫХ ПРОБЕЛОМ) - array ;------------------------------------------------------------- ReadArray proc push cx ; сохранение регистров push bx push dx push di push si mov di,-2 mov si,-1 start_ra: inc si add di,2 ;увеличение индекса очередного элемента массива cmp si, count ;проверка на превышение размера массива je end_ra xor cx, cx mov bx, 10 call ReadChar ; ввод первого символа cmp al,'-' ; если минус - ошибка ввода je wrong_input jmp not_minus_ra read_ra: call ReadChar ; ввод очередного символа not_minus_ra: cmp al, ' ' ; Space ? je done_ra ; да - > завершение ввода числа cmp al, 13 ; Enter ? je end_ra ; да - > завершение ввода sub al, '0' ; нет -> перевод цифры char -> int xor ah, ah xor dx, dx xchg cx, ax mul bx add ax, cx xchg ax, cx jmp read_ra done_ra: xchg array[di], cx jmp start_ra end_ra: xchg array[di], cx pop si pop di pop dx pop bx pop cx ret ReadArray endp ;------------------------------------------------------------- ;ВВОД ОДНОГО СИМВОЛА ;------------------------------------------------------------- ReadChar proc mov ah,1 int 21h ret ReadChar endp ;------------------------------------------------------------- ;РАСЧЕТ АБСЦИСС ТОЧЕК КРИВОЙ ;------------------------------------------------------------- GetLines proc push ax ;сохранение регистров push bx push cx push dx push di push si mov ax,count ;кол-во итераций sub ax, 1 ;для цикла mov cx, ax ;равно count-1 mov di, 0 ;индексы для извлечения из array mov si, 2 mov x1, 1 mov x2, 2 mov index,-2 ;устанавливаем переменные для добавления точек mov value,1 ;call AddX L: ;цикл для расчета точек кривой ;cчитаем пересечение (x1,y1)(x2,y2+1)c Y mov sp, array[di] mov bx, array[si] mov y1, sp mov y2, bx inc y2 ;y2 = y2+1 call CalculateY mov max_calc,ax ;cчитаем пересечение (x1,y1+1)(x2,y2)c Y inc y1 dec y2 call CalculateY ;определяем интервал min,max mov min_calc,ax cmp max_calc,ax jnle not_replace jng replace replace: mov bx,max_calc mov max_calc,ax mov min_calc,bx not_replace: ;проверяем отрезок - первый? (min==0 && max==0) cmp min,0 je a jne not_first a: cmp max,0 je first jne not_first ;если первый - устанавливаем max, min first: mov ax, max_calc mov max, ax mov ax, min_calc mov min, ax jmp add_point not_first: ;определяем пересечение интервалов call AddIntervals ;если интервалы не пересекаются, добавляем точку к ломаной cmp min,0 je b jne end_iteration b: cmp max,0 je add_point jne end_iteration add_point: add index,2 call AddX end_iteration: add di,2 ;увеличиваем счетчики add si,2 inc x1 inc x2 inc value loop L ;конец цикла add index,2 ;добавляем к ломаной последнюю точку call AddX pop si pop di pop dx pop cx pop bx pop ax jmp exit ;ret GetLines endp ;------------------------------------------------------------- ;x1,x2,y1,y2(x2=x1+1)- две точки через которые проходит прямая ;вычисляем в AX ординату пересечения прямой и оси Y ;------------------------------------------------------------- CalculateY proc push cx ;сохранение регистров push bx mov ax,x2 mul y1 mov bx,ax ;bx = y1*x2 mov ax,y2 mul x1 mov cx,ax ;cx = x1*y2 sub bx,cx ;bx = y1*x2 - y2*x1 mov ax,bx pop bx pop cx ret CalculateY endp ;------------------------------------------------------------- ;ДОБАВЛЕНИЕ value В x[index] ;------------------------------------------------------------- AddX proc push di push ax mov di,index mov ax,value mov x[di],ax pop ax pop di ret AddX endp ;------------------------------------------------------------- ; [min;max] U [min_calc;max_calc] - пересечение ; Если рез-т нулевой, то max=0, min=0 ;------------------------------------------------------------- AddIntervals proc push ax push bx ;gпроверка на то, что интервалы не пересекаются mov ax,max_calc cmp ax,min jng zero_ai mov ax,min_calc cmp ax,max jnl zero_ai ;если max_calc < max => max = max_calc mov ax, max_calc cmp ax, max jnge less jmp min_check less: mov bx, max_calc mov max, bx ;если min_calc > min => min = min_calc min_check: mov ax, min_calc cmp ax, min jnle more jmp end_ai more: mov bx, min_calc mov min, bx end_ai: pop bx pop ax ret ;интервалы не пересекаются zero_ai: mov max,0 mov min,0 pop bx pop ax ret AddIntervals endp ends end start ; set entry point and stop the assembler.
Это эмулятор доса(ntvdm), GUI не поддерживается. Нужно два процесса создавать, первый - враппер который запустит ntvdm и создаст GUI-окно.
Если кто-нибудь поделится реализацией алгоритма Брезенхэма или просто процедурой отрисовки линии между двумя точками, то очень мне поможет. А то пока не нагуглил ничего.
Только на MASMе. Когда-то, давно игрался. Отрабатывал алгос, на AVR нужно было написать прогу для работы с графикой на LCD. Код (Text): ; ;BrezLineCreate PROTO :DWORD,:DWORD,:DWORD,:DWORD ;BrezLineFree PROTO :DWORD ;BrezLineGetPixel PROTO :DWORD ;BrezLineNextPixel PROTO :DWORD ; BREZLINE STRUCT X DD ? Y DD ? delta_x DD ? delta_y DD ? XErr DD ? YErr DD ? incX DD ? incY DD ? delta DD ? BREZLINE ends .code BrezLineCreate proc USES EBX x_1:DWORD,y_1:DWORD,x_2:DWORD,y_2:DWORD invoke GetProcessHeap invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,sizeof BREZLINE ; push eax ; mov ebx, [x_1] mov [eax+BREZLINE.X], ebx mov ebx, [y_1] mov [eax+BREZLINE.Y], ebx xor ebx, ebx mov [eax+BREZLINE.XErr],ebx mov [eax+BREZLINE.YErr],ebx mov [eax+BREZLINE.incX],ebx mov [eax+BREZLINE.incY],ebx mov ebx, [x_2] sub ebx, [x_1] mov [eax+BREZLINE.delta_x], ebx .if SIGN? neg [eax+BREZLINE.delta_x] dec [eax+BREZLINE.incX] ;mov incX, -1 .elseif ZERO? ;nop ;mov incX, 0 .else inc [eax+BREZLINE.incX] ;mov incX, 1 .endif mov ebx, [y_2] sub ebx, [y_1] mov [eax+BREZLINE.delta_y], ebx .if SIGN? neg [eax+BREZLINE.delta_y] dec [eax+BREZLINE.incY] ;mov incX, -1 .elseif ZERO? ;nop ;mov incX, 0 .else inc [eax+BREZLINE.incY] ;mov incX, 1 .endif mov ebx, [eax+BREZLINE.delta_x] .if ebx > [eax+BREZLINE.delta_y] ;mov [eax+BREZLINE.delta],ebx .else mov ebx, [eax+BREZLINE.delta_y] .endif mov [eax+BREZLINE.delta], ebx ; ; pop eax ret BrezLineCreate endp BrezLineFree proc hBrzLine:DWORD invoke GetProcessHeap invoke HeapFree,eax,NULL,[hBrzLine] ret BrezLineFree endp BrezLineNextPixel proc USES esi hBrzLine:DWORD mov esi, [hBrzLine] mov eax, [esi+BREZLINE.delta_x] add eax, [esi+BREZLINE.XErr] .if eax > [esi+BREZLINE.delta] sub eax, [esi+BREZLINE.delta] mov [esi+BREZLINE.XErr], eax mov eax, [esi+BREZLINE.incX] add [esi+BREZLINE.X], eax .else mov [esi+BREZLINE.XErr], eax .endif mov eax, [esi+BREZLINE.delta_y] add eax, [esi+BREZLINE.YErr] .if eax > [esi+BREZLINE.delta] sub eax, [esi+BREZLINE.delta] mov [esi+BREZLINE.YErr], eax mov eax, [esi+BREZLINE.incY] add [esi+BREZLINE.Y], eax .else mov [esi+BREZLINE.YErr], eax .endif ;dec [esi+BREZLINE.delta] mov eax, [esi+BREZLINE.delta] ret BrezLineNextPixel endp BrezLineGetPixel proc USES esi hBrzLine:DWORD mov esi, [hBrzLine] mov eax, [esi+BREZLINE.Y] shl eax, 16 mov ax, word ptr [esi+BREZLINE.X] ret BrezLineGetPixel endp Должно работать.
Задам вопрос здесь, чтобы не плодить темы. Мне нужно воспользоватся сопроцессором. Я написал такой код: Код (Text): ; multi-segment executable file template. data segment ; add your data here! pkey db "press any key...$" ends stack segment dw 128 dup(0) ends code segment start: ; set segment registers: mov ax, data mov ds, ax mov es, ax ; add your code here finit lea dx, pkey mov ah, 9 int 21h ; output string at ds:dx ; wait for any key.... mov ah, 1 int 21h mov ax, 4c00h ; exit to operating system. int 21h ends end start ; set entry point and stop the assembler. Это сгенерированный код, я добавил только finit И получил ошибку такого содержания Код (Text): (20) illegal instruction: finit or wrong parameters. Нашел пример на фасме, в котором используется сопроцессор. там указывается Код (Text): format PE Запустил этот пример, все работает. Но мне не надо format PE. Мне нужно просто заюзать сопроцессор.