Эффект дождь Размер COM-файла 701 байт. Во вложении исходный текст, картинка в формате PCX и COM-файл Код (ASM): ; masm dos com # .model tiny .code .686 org 100h PALSIZE equ 256*3 WIDTH_SCREEN equ 320 HEIGHT_SCREEN equ 200 SIZESCREEN equ WIDTH_SCREEN*HEIGHT_SCREEN VGA_SEGMENT equ 0A000h PCXBUFSIZE equ 400h PCX_HEADER struct PCX_manufacturer db ?; manufacturer byte (always 0A0h) PCX_version db ?; pcx Version PCX_encoding db ?; (always 1) PCX_bits_per_pixel db ?; color bits per pixel PCX_xmin dw ?; image origin x PCX_ymin dw ?; image origin y PCX_xmax dw ?; image end x PCX_ymax dw ?; image end y PCX_hres dw ?; horizontal resolution PCX_vres dw ?; vertical resolution PCX_palette1 db 48 dup(?);(color palette, for older not 256 col vers.) PCX_reserved db ?; reserved byte PCX_color_planes db ?; number of color planes PCX_bytes_per_line dw ?; line buffer size PCX_palette_type dw ?; grey or color palette indicator PCX_reserved2 db 58 dup(?);reserved PCX_HEADER ends start proc local xcount:word local ycount:word local local_bytesperline:word local readbuf[400h]:byte local hpcx:PCX_HEADER local temp:dword local buf3_seg:word local LineTable[HEIGHT_SCREEN]:word mov ax, 13h int 10h mov dx, 3C4h; индексный регистр последовательного контроллера mov al, 4;MEMORY MODE; индекс регистра режима выбора памяти out dx, al inc dx in al, dx and al, 0F7h;выключим адресацию по 4 байта or al, 4 ;выключим чет/нечет out dx, al mov dx, 3CEh; индексный регистр графического контроллера mov al, 5;GRAPHICS MODE ;индекс регистра графического режима out dx, al inc dx in al, dx and al, 0EFh;выключим чет/нечет out dx, al dec dx mov al, 6;MISCELLANEOUS;индекс дополнительного регистра out dx, al inc dx in al, dx and al, 0FDh;выключим последовательности out dx, al ;разрешим запись во все плоскости, чтобы мы могли очистить по 4 плоскости за один раз mov dx, 3C4h; индексный регистр последовательного контроллера mov ax,0F02h;2 - индекс регистра маски карты, 0F - 4 плоскости out dx,ax; al push VGA_SEGMENT pop es xor di, di xor ax, ax mov cx, 8000h; число слов в 64 Кбайт rep stosw; чистим видеопамять ;переключение в режим 320х400 256 цветов не сканируя каждую линию дважды mov dx, 3D4h;индексный регистр КЭЛТ mov al, 9;MAX_SCAN_LINE;индекс регистра максимальной линии сканирования в КЭЛТ out dx, al inc dx in al, dx and al, 0E0h;установим максимальную линию сканирования = 0 out dx, al dec dx ;изменим сканирование КЭЛТ и перейдем от 4-байтового режима в 1-байтовый, ;позволив КЭЛТ сканировать более 64 Кбайт видеопамяти mov al, 14h;UNDERLINE;индекс регистра позиции подчеркивания в КЭЛТ out dx, al inc dx in al, dx and al, 0BFh;выключим 4-байтовый режим out dx, al dec dx mov al, 17h;MODE CONTROL;регистр управления режимом в КЭЛТ out dx, al inc dx in al, dx or al, 40h;включим побайтовый режим, чтобы память ;сканировалась как бы линейно, как в режимах 10h и 12h out dx, al mov ax, cs add ah, 10h mov gs,ax add ah, 10h mov fs,ax add ah, 10h mov buf3_seg, ax ;SetupLineTable push ss pop es lea di,LineTable xor ax, ax mov cx, HEIGHT_SCREEN @@: stosw add ax, WIDTH_SCREEN loop @b ;RANDOMIZE() rdtsc mov temp, eax ;CleanSegments xor eax, eax xor di, di push gs pop es; es=buf1_seg mov cx, 8000h rep stosd ;load PCX mov dx,offset filename; OPEN DISK FILE ONLY FOR READ mov ax,3D00h ;WITH HANDLE int 21h ; DS:DX -> ASCIZ filename mov bx, ax mov cx, 80h ;sizeof(hpcx) lea dx,hpcx ;#hpcx mov ah, 3Fh; READ FROM FILE WITH HANDLE int 21h; BX = file handle, CX = number of bytes to read, DS:DX -> buffer mov ax,hpcx.PCX_ymax sub ax,hpcx.PCX_ymin inc ax mov ycount, ax ;ycount=hpcx.PCX_ymax-hpcx.PCX_ymin+1 mov ax,hpcx.PCX_xmax sub ax,hpcx.PCX_xmin inc ax mov local_bytesperline,ax;local_bytesperline=hpcx.PCX_xmax-hpcx.PCX_xmin+1 push fs pop es ;es=buf2_seg xor di, di mov si, PCXBUFSIZE;SI=PCXBUFSIZE @0: mov ax,local_bytesperline mov xcount,ax ;xcount=local_bytesperline @1: cmp si, PCXBUFSIZE ;IF(SI==PCXBUFSIZE) jnz @f mov cx,PCXBUFSIZE lea dx,readbuf mov ah, 3Fh; READ FROM FILE WITH HANDLE int 21h; BX = file handle, CX = number of bytes to read, DS:DX -> buffer xor si, si @@: mov al,readbuf[si] inc si cmp al, 0C0h;IF(AL>=0xC0) jb @f and al, 3Fh ;AL &= 0x3F xor cx, cx mov cl, al sub xcount,cx ;xcount-=CX cmp si, PCXBUFSIZE ;IF(SI==PCXBUFSIZE) jnz @2 push cx mov cx, PCXBUFSIZE lea dx,readbuf ;#readbuf mov ah, 3Fh; READ FROM FILE WITH HANDLE, BX = file handle, int 21h; CX = number of bytes to read, DS:DX -> buffer pop cx xor si, si @2: mov al,readbuf[si] inc si rep stosb jmp short @3 @@: dec xcount stosb @3: cmp xcount,0 ja @1 dec ycount jnz @0 mov cx, -1 mov dx,-(PALSIZE+1) mov ax, 4202h int 21h ; MOVE FILE READ/WRITE POINTER (LSEEK) ; AL = method: offset from end of file mov cx, PALSIZE+1 lea dx,readbuf;#readbuf mov ah, 3Fh; READ FROM FILE WITH HANDLE int 21h; BX = file handle, CX = number of bytes to read, DS:DX -> buffer lea di,readbuf+1 mov cx, PALSIZE @@: shr byte ptr [di], 2 inc di loop @b ;SETVGADAC(0,,768,,,#readbuf[1]) xor ax, ax mov cx, PALSIZE lea si,readbuf+1 mov dx, 3C8h out dx, al inc dx rep outsb mov ah, 3Eh; CLOSE A FILE WITH HANDLE int 21h ; BX = file handle ;CHANGEPICTOR xor si, si xor dx, dx push VGA_SEGMENT pop es @4: xor di, di @@: push dx mov cx, di ;WRITEPIXEL400 push di imul di,dx,80 push cx shr cx, 2 add di,cx pop cx and cl, 3 mov ah, 1 shl ah, cl mov dx, 3C4h; EGA: sequencer address reg mov al, 2; sequencer reset. out dx, ax; Bits of data 0-1 indicate asynchronous/synchronous reset. movs byte ptr es:[di],fs:[si] pop di pop dx inc di cmp di, WIDTH_SCREEN jb @b inc dx cmp dx, HEIGHT_SCREEN jb @4
Код (ASM): xor di, di mov dx, HEIGHT_SCREEN-1 @5: xor si, si @@: push dx mov cx, si push si imul si,dx,80 push cx shr cx, 2 add si, cx pop cx and cl, 3 mov ah, cl mov dx, 3CEh mov al, 4 out dx, ax ; EGA: graph 1 and 2 addr reg: ; set/reset. ; Data bits 0-3 select planes for write mode 00 mov al, es:[si] pop si pop dx mov fs:[di],al inc di inc si cmp si, WIDTH_SCREEN jb @b dec dx jns short @5 mainloop:;SetRandomPoint mov ax,word ptr temp+2 mov cx,word ptr temp shld ax,cx,8 shl cx,8 rcr ax, 1 rcr cx, 1 add word ptr temp, cx adc ax, word ptr temp+2 add word ptr temp, 25321 adc ax, 13849 mov word ptr temp+2, ax xor dx, dx mov cx, SIZESCREEN div cx mov bx, dx mov byte ptr gs:[bx], 7Fh ;DoWater mov es, buf3_seg xor ax, ax xor di, di;cx=SIZESCREEN @6: xor bx, bx lea si, gs:[di-WIDTH_SCREEN-1] lods byte ptr gs:[si] add bx, ax lods byte ptr gs:[si] add bx, ax lods byte ptr gs:[si] add bx, ax add si, WIDTH_SCREEN-3 lods byte ptr gs:[si] add bx, ax lods byte ptr gs:[si] add bx, ax lods byte ptr gs:[si] add bx, ax add si, WIDTH_SCREEN-3 lods byte ptr gs:[si] add bx, ax lods byte ptr gs:[si] add bx,ax lods byte ptr gs:[si] add ax,bx add si,WIDTH_SCREEN-3 sub al,gs:[di] sbb ah,0 sar ax,2 sub al,es:[di] jns @f xor ax,ax @@: stosb loop @6 ;DupeToScreen push VGA_SEGMENT pop es xor si,si mov dx,HEIGHT_SCREEN @7: xor di,di @@: xor bx,bx mov bl,gs:[si] push si mov ax,si shl bx,1 mov si,bx add si,LineTable[si] add si,ax push dx mov cx,di ;WRITEPIXEL400 push di imul di,dx,80 push cx shr cx,2 add di,cx pop cx and cl,3 mov ah,1 shl ah,cl mov dx,3C4h ; EGA: sequencer address reg mov al,2 ; sequencer reset. out dx,ax ; Bits of data 0-1 indicate asynchronous/synchronous reset. movs byte ptr es:[di],fs:[si] pop di pop dx pop si inc si inc di cmp di,WIDTH_SCREEN jb @b inc dx cmp dx,HEIGHT_SCREEN*2 jb @7 push gs push buf3_seg pop gs ; buf1_seg <--> buf3_seg pop buf3_seg mov ah, 1 int 16h ; KEYBOARD - CHECK BUFFER, DO NOT CLEAR jz mainloop mov ax, 3 int 10h ; - VIDEO - SET VIDEO MODE int 20h start endp filename db 'forest.pcx',0 end start