· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.ASSEMBLER —› Помогите с програмкой на Фасме

Посл.отвђт Сообщенiе


Дата: Июн 28, 2003 16:51:00 · Поправил: Безпощадный даос

Ну знатоки ассемблера, выручайте. Имеется програмка. Переделана с Зубкова под фасм - эффект огня через LFB. Вроде работает, и нормально, да вот есть 2 глюка:
1) ИНОГДА (1/10) происходит фигня: прога запускается не на полный экран, винда орет как угорелая что мол восстановление не возможно(на полный экран) а в это время прога спокойненько рисуе пламя прямо в винде - в смысле над рабочим столом!
2) Странный глюк переменных, для которым мы только отводим место: если они (в частности buffer - буфер для экрана) не идут последними, то занимают полный обьем. +300kb к программе как-то не хочется. Если их поместить в конец, но изначально они не пустые! т.е. в них записан какой-то хлам.(наглядно видно на экране в начале программы.)

Заранее благодарен всем.

Собсно прога
------------------CUT----------------

; fasm example of writing 32-bit program using DPMI

; requires DPMI host installed in system

format MZ
heap 0					; no additional memory

segment loader use16

	push	cs
	pop	ds

	mov	ax,1687h
	int	2Fh
	or	ax,ax			; DPMI installed?
	jnz	DPMI_error2
	test	bl,1			; 32-bit programs supported?
	jz	DPMI_error2
	mov	word [mode_switch],di
	mov	word [mode_switch+2],es
	mov	bx,si			; allocate memory for DPMI data
	mov	ah,48h
	int	21h
	jc	DPMI_error2
	mov	es,ax
	mov	ax,1
	call	far [mode_switch]	; switch to protected mode
	jc	DPMI_error2

	mov	cx,1
	xor	ax,ax
	int	31h			; allocate descriptor for code
	mov	si,ax
	xor	ax,ax
	int	31h			; allocate descriptor for data
	mov	di,ax
	mov	dx,cs
	lar	cx,dx
	shr	cx,8
	or	cx,0C000h
	mov	bx,si
	mov	ax,9
	int	31h			; set code descriptor access rights
	mov	dx,ds
	lar	cx,dx
	shr	cx,8
	or	cx,0C000h
	mov	bx,di
	int	31h			; set data descriptor access rights
	mov	ecx,main
	shl	ecx,4
	mov	dx,cx
	shr	ecx,16
	mov	ax,7			; set descriptor base address
	int	31h
	mov	bx,si
	int	31h
	mov	cx,0FFFFh
	mov	dx,0FFFFh
	mov	ax,8			; set segment limit to 4 GB
	int	31h
	mov	bx,di
	int	31h

	mov	ds,di
	mov	es,di
	mov	fs,di
	mov	gs,di
	push	si
	push	dword start
	retfd

DPMI_error2:	 ; ошибка при выполнении одной из функций DPMI
	mov	ax,03h		; восстановить текстовый режим
	int	10h

        lea     edx,[DPMI_error_msg2]
	mov	ah,9
	int	21h			; вывести сообщение об ошибке

	mov	ax,4C00h	; AH = 4Ch
	int	21h		; выход из программы под расширителем DOS

DPMI_error_msg2  db      'DPMI error or not installed Cant contiue$'

  mode_switch dd ?

segment main use32

  start:

	mov	ax,0100h	; функция DPMI 0100h
	mov	bx,100h ; размер в 16-байтных параграфах
	int	31h		; выделить блок памяти ниже 1 Мб
	jc	DPMI_error
	mov	fs,dx		; FS - селектор для выделенного блока

	mov	dword [fs:0],'2EBV' ; сигнатура VBE2 в начало блока
	mov	word ptr v86_eax,4F00h	; функция VBE 00h
	mov	word ptr v86_es,ax	; сегмент, выделенный DPMI
	mov	ax,0300h	; функция DPMI 300h
	mov	bx,0010h	; эмуляция прерывания 10h
	xor	ecx,ecx
	lea	edi,[v86_regs]
	push	ds
	pop	es		; ES:EDI - структура v86_regs
	int	31h		; получить общую информацию VBE2
	jc	DPMI_error
	cmp	byte ptr v86_eax,4Fh	; проверка поддержки VBE
	jne	VBE_error

	movzx	ebp,word [fs:18]    ; объем SVGA-памяти в EBP
	shl	ebp,6


	mov	word ptr v86_eax,4F01h	; номер функции INT 10h
	mov	word ptr v86_ecx,101h	; режим 101h - 640x480x256
					; ES:EDI те же самые
	mov	ax,0300h	; функция DPMI 300h - эмуляция прерывания
	mov	bx,0010h	; INT 10h
	xor	ecx,ecx
	int	31h		; получить данные о режиме
	jc	DPMI_error
	cmp	byte ptr v86_eax,4Fh
	jne	VBE_error
	test	byte [fs:0],80h ; бит 7 байта атрибутов = 1 - LFB есть
	jz	LFB_error

	mov	eax,ebp 	; видеопамять в килобайтах
	shl	eax,10		; теперь в байтах
	dec	eax			; лимит = размер - 1
	shr	eax,12		; лимит в 4-килобайтных единицах
	mov	word ptr videodsc+0,ax	; записать биты 15 - 0 лимита
	shr	eax,8
	and	ah,0Fh
	or	byte ptr videodsc+6,ah	; и биты 19 - 16 лимита

	mov	eax,ebp 	; видеопамять в килобайтах
	shl	eax,10		; в байтах
	mov	edx,dword [fs:40]   ; физический адрес LFB
	mov	cx,dx
	shld	ebx,edx,16		; поместить его в CX:DX,
	mov	di,ax
	shld	eax,eax,16		; а размер - в SI:DI
	mov esi,eax
	mov	ax,800h 	; и вызвать функцию DPMI 0800h
	int	31h			; отобразить физический адрес в линейный
	jc	DPMI_error
       shrd    edx,ebx,16	       ; перенести полученный линейный адрес
	mov	dx,cx			; из BS:CX в EDX
	mov	word ptr videodsc+2,dx	; и записать биты 15 - 0 базы
	shr	edx,16
	mov	byte ptr videodsc+4,dl	; биты 23 - 16
	mov	byte ptr videodsc+7,dh	; и биты 31 - 24

	mov	bx,cs
	lar	cx,bx			; прочитать права нашего сегмента
	and	cx,6000h		; и перенести биты DPL
	or	byte ptr videodsc+5,ch	; в строящийся дескриптор

		mov	cx,1		; получить один новый дескриптор
	mov	ax,0		; у DPMI
	int	31h
	jc	DPMI_error
	mov	word ptr videosel,ax	; записать его селектор

	push	ds
	pop	es
	lea	ebx,[videodsc] ; ES:EDI - адрес нашего дескриптора
	mov	edi,ebx
	mov	bx,ax			; BX - выданный нам селектор
	mov	ax,0Ch		; функция DPMI 0Ch
	int	31h		; загрузить дескриптор в LDT
	jc	DPMI_error	; теперь в videosel лежит селектор на LFB

		mov word ptr v86_eax,4F02h	; 4F02h - установить SVGA-режим
	mov word ptr v86_ebx,4101h	; режим 4101h = 101h + LFB
	lea	eax,[v86_regs]	   ; ES:EDI - структура v86_regs
	mov	edi,eax
	mov	ax,0300h	; функция DPMI 300h
	mov	bx,0010h	; эмуляция прерывания 10h
	xor	ecx,ecx
	int	31h

	mov	ax,word ptr videosel	; AX - наш селектор
      enter_flame:    ; сюда придет управление с селектором в ax на A000h:0000,
		      ; если произошла ошибка в любой VBE-функции
	mov	es,ax ; ES - селектор видеопамяти или LFB

; отсюда начинается процедура генерации пламени

; генерация палитры для пламени
	xor	edi,edi ; начать писать палитру с адреса ES:0000
	xor	ecx,ecx
palette_gen:
	xor	eax,eax ; цвета начинаются с 0, 0, 0
	mov	cl,63		; число значений для одной компоненты
palette_l1:
	stosb		; записать байт
	inc	eax	; увеличить компоненту
	cmpsw		; пропустить два байта
	loop	palette_l1 ; и так 64 раза

	push	edi
	mov	cl,192
palette_l2:
	stosw		; записать два байта
	inc	di	; и пропустить один
	loop	palette_l2 ; и так 192 раза (до конца палитры)
	pop	edi	; восстановить EDI
	inc	di
	jns	palette_gen



; палитра сгенерирована, записать ее в регистры VGA DAC
	mov	al,0		; начать с регистра 0
	mov	dx,03C8h	; индексный регистр на запись
	out	dx,al
	push	es
	push	ds	; поменять местами ES и DS
	pop	es
	pop	ds
	xor	esi,esi
	mov	ecx,256*3	; писать все 256 регистров
	mov	edx,03C9h	; в порт данных VGA DAC
	rep outsb
	push	es
	push	ds	; поменять местами ES и DS
	pop	es
	pop	ds

; основной цикл - анимация пламени, пока не будет нажата любая клавиша,
	xor	edx,edx 	; должен быть равен нулю
	mov	ebp,1111h		; любое число
	mov	ecx,scr_width ; ширина экрана
main_loop:
	push	es		; сохранить ES
	push	ds
	pop	es		; ES = DS - мы работаем только с буфером
; анимация пламени (классический алгоритм)
	inc	ecx
	lea	edi,[buffer]
	mov	ebx,dword ptr scr_height
	shr	ebx,1
	dec	ebx
	mov	esi,[scr_width]
animate_flame:
	mov	ax,[edi+esi*2-1]	; вычислить среднее значение цвета
	add	al,ah			; в данной точке (EDI) из значений
	setc	ah			; цвета в точке слева и на две строки
	;mov	 dl,[edi+esi*2+1]	 ; вниз, справа и на две строки вниз
	add	ax,dx
	mov	dl,[edi+esi*4]	; и на четыре строки вниз,
	add	ax,dx			; причем первое значение

	shr	ax,2			; модифицировать

	jz	already_zero	; уменьшить яркость цвета
	dec	ax
already_zero:
	stosb			; записать новый цвет в буфер
	add	eax,edx
	shr	eax,1
	mov	byte [edi+esi-1],al
	loop	animate_flame
	mov	ecx,esi
	add	edi,ecx
	dec	ebx
	jnz	animate_flame

; псевдослучайная полоска внизу экрана, которая служит генератором пламени
generator_bar:
	xadd	bp,ax
	stosw
	stosw
	loop	generator_bar

	pop	es	; восстановить ES для вывода на экран
			; вывод пламени на экран
			; ES:EDI - LFB
	push	esi
	xor	edi,edi

	lea	ecx,[buffer]			; DS:ESI - буфер
	add	esi,ecx

	mov	ecx,dword [scr_size]		; размер буфера в двойных словах
	sub	ecx,640*2
	rep	movsd				; скопировать буфер на экран
	pop	esi

	mov	ah,1		; если не была нажата
	int	16h		; никакая клавиша,
	jz	main_loop	; продолжить основной цикл,
	mov	ah,0		; иначе -
	int	16h		; считать эту клавишу

exit_all:
	mov	ax,03h		; восстановить текстовый режим
	int	10h
	mov	ax,4C00h	; AH = 4Ch
	int	21h		; выход из программы под расширителем DOS

; различные обработчики ошибок
DPMI_error:	; ошибка при выполнении одной из функций DPMI

	lea	 edx,[DPMI_error_msg]
	mov	ah,9
	int	21h			; вывести сообщение об ошибке
	jmp near exit_all      ; и выйти
VBE_error:	; не поддерживается VBE
		lea	 edx,[VBE_error_msg]

	mov	ah,9
	int	21h		; вывести сообщение об ошибке
	jmp near start_with_vga2	; и использовать VGA
LFB_error:	; не поддерживается LFB
	lea	edx,[LFB_error_msg]
	mov	ah,9		; вывести сообщение об ошибке
	int	21h
start_with_vga2:
	mov	ah,0		; подождать нажатия любой клавиши
	int	16h
	mov	ax,13h	; переключиться в видеорежим 13h
	int	10h		; 320x200x256
	mov	ax,2		; функция DPMI 0002h
	mov	bx,0A000h	; построить дескриптор для реального
	int	31h		; сегмента
	mov	dword ptr scr_width,320 ; установить параметры
	mov	dword ptr scr_height,200		; режима
	mov	dword ptr scr_size,320*200/4
	jmp enter_flame 	; и перейти к пламени

;	 .data
; различные сообщения об ошибках
VBE_error_msg	db	'VBE 2.0 error',0Dh,0Ah
		db	'Will use VGA 320x200 mode'
		db	0Dh,0Ah,'$'
DPMI_error_msg	db	'DPMI error$'
LFB_error_msg	db	'Linear Framebuffer not '
		db	'availiable',0Dh,0Ah
		db	'Will use VGA 320x200 mode'
		db	0Dh,0Ah,'$'
; параметры видеорежима
scr_width	dd	640
scr_height	dd	480
scr_size	dd	640*480/4
; структура, используемая функцией DPMI 0300h
    label v86_regs
v86_edi     rd		1
v86_esi     rd		1
v86_ebp     rd		1
v86_res     rd		1
v86_ebx     rd		1
v86_edx     rd		1
v86_ecx     rd		1
v86_eax     rd		1
v86_flags   rw		1
v86_es	    rw		1
v86_ds	    rw		1
v86_fs	    rw		1
v86_gs	    rw		1
v86_ip	    rw		1
v86_cs	    rw		1
v86_sp	    rw		1
v86_ss	    rw		1
; дескриптор сегмента, соответствующего LFB
videodsc	dw	0	; биты 15 - 0 лимита
		dw	0	; биты 15 - 0 базы
		db	0	; биты 16 - 23 базы
		db	10010010b	; доступ
		db	10000000b	; биты 16 - 19 лимита и другие биты
		db	0	; биты 24 - 31 базы
; селектор сегмента, описывающего LFB
videosel    dw		0
;; буфер для экрана
hello	    db		'Hello from protected mode!',0Dh,0Ah,0
MemDesk     dw		0

buffer rb  640*480

;wMemDesk     dw	  0
------------------CUT----------------


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.089