Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2455
∙ повысить рейтинг »
_Ayl_
Статус: Профессионал
Рейтинг: 1857
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1227
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска:1352
Дата выхода:04.06.2010, 02:00
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:255 / 61
Вопросов / ответов:2 / 2
IRC-канал по теме:#assembler

Вопрос № 178499: Здравствуйте, эксперты! Помогите, пожалуйста, написать программу которая скачивает главную страницу сайта (сайт задается в самой программе) и сохраняет ее на локальный диск. Это должна быть консольная, неинтерактивная программка. Хорошо бы ещ...


Вопрос № 178723: Уважаемые эксперты, подскажите, пожалуйста, как скомпилировать приведённую ниже в листинге программу. В ней пропущена только модель памяти и модель процессора? У меня не хочет даже ассемблироваться. Этот листинг я скопировал из книги Абраша «Таинства...

Вопрос № 178499:

Здравствуйте, эксперты!
Помогите, пожалуйста, написать программу которая скачивает главную страницу сайта (сайт задается в самой программе) и сохраняет ее на локальный диск.
Это должна быть консольная, неинтерактивная программка. Хорошо бы еще с комментариями, чтобы лучше понять, как сие работает.
Компилятор MASM.
Спасибо.

Отправлен: 19.05.2010, 18:30
Вопрос задал: AtomIad, 5-й класс
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, AtomIad.
Держите программу, которая открывает сокет, посылает запрос на сервер и получает страницу в буфер
Сохранение в виде файла, надеюсь, проблем не вызовет?
Обратите внимание, в начале принимается служебная информация, типа такого:
Код:
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 03 Jun 2010 07:36:34 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.2.8
Last-Modified: Thu, 03 Jun 2010 11:36:34 +0400

Так что, начало самой страницы ищем по байту '<' и пишем в файл...
Код:

.586
.model FLAT, STDCALL
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\wsock32.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\shlwapi.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\wsock32.lib
includelib \masm32\lib\shlwapi.lib

String2Dword PROTO :DWORD
OpenURL PROTO :DWORD

.data
ourURL db 'http://www.codenet.ru/', 0 ;адрес сайта
http db 'http://', 0 ;для проверки на протокол http
Conecting db 'Conecting to %d.%d.%d.%d...', 0;сообщение о соединении
Ok db 'Ok', 0ah ;соединение свершилось
none db 0 ;и как конец Ok, и как пустая строка
fquery db 'GET /% s HTTP/1.0', 0ah, 'Host: %s' ;строка формата для строки запроса
db 0ah, 'User-agent: GetPage v1.0', 0ah, 'Accept: */*', 0ah, 0ah, 0
ErrorMess db 'Error #%d: WSABASEERR+%d', 0ah, 0 ;сообщение об ошибке

.data?
sock dd ? ;сокет
Rec db 204800 dup (?) ;буфер для приема данных
;(лучше запросить память, но для теста годится)

.code

main: invoke OpenURL, addr ourURL ;открываем URL, запрашиваем и принимаем страницу
test eax, eax ;eax - код ошибки, 0 - ок
je URL_ok
mov esi, eax
call WSAGetLastError
sub eax, WSABASEERR
invoke wsprintf, addr Rec, addr ErrorMess, esi, eax
invoke StdOut, addr Rec
jmp ToCloseURL
URL_ok:
invoke StdOut, addr Rec ;просто выведем на экран
;здесь можно вставить процедуру для сохранения в файл (ecx - длина)
ToCloseURL:
call CloseURL ;закрываем соединение

invoke ExitProcess, 0 ;выход

;посылка строки-запроса на сервер
;параметры: s - сокет, pStr - адрес строки
;результат: al = 1 - ок
SendString proc uses edi s:dword, pStr:dword
;посчитаем в ecx длину строки
mov edi, pStr
or ecx, -1
xor eax, eax
repne scasb
not ecx
dec ecx

;посылаем
invoke send, s, pStr, ecx, 0
cmp eax, -1
setne al
ret
SendString endp

;получения ответа от сервера
;параметр: s - сокет
;результат: eax = 0 - ok, eax=6 - ошибка
GetString proc uses esi edi ebx s:dword
local InBuff[2048]:byte ;буфер для приема части ответа

lea ebx, InBuff ;временный буфер
lea esi, Rec ;буфер, куда пишем всю строку
mov byte ptr [esi], 0 ;сделаем пустой
GS_loop:
mov ecx, 2048/4 ;длина в dword-ах
xor eax, eax ;обнулим
mov edi, ebx ;InBuff
rep stosd

;принимаем 2048 байт в InBuf=[ebx]
invoke recv, s, ebx, 2048, eax
cmp eax, -1 ;проверим на ошибку
je GS_error
mov edx, eax ;сохраним длин у принятого сообщения

;скопируем принятый фрагмент на свое место в результирующий буфер
mov edi, esi
mov esi, ebx ;Inbuff mov ecx, edx ;длина
shr ecx, 2
rep movsd ;для убыстрения копируем dword-ами
mov ecx, edx
and ecx, 3
rep movsb ;оставшийся "хвостик"
mov esi, edi ;esi - адрес конца в буфере Rec

test edx, edx ;если приняли 0 байт, то конец
jne GS_loop

mov ecx, esi ;ecx = длине принятых данных
sub ecx, offset Rec
xor eax, eax ;все ок
GS_ret:
ret
GS_error:
mov eax, 6 ;код ошибки
jmp GS_ret
GetString endp

;открываем url, посылаем запрос и получаем ответ
OpenURL proc uses ebx esi edi url:dword
local WSAData:WSADATA ;для информации о сокетах
local query[2048]:byte ;буфер для строки запросов
local ssin:sockaddr_in ;для задания IP
local http_host[2048]:byte ;буфер для имени хоста
local http_path:dword ;адрес строки с путем (все, что за именем хоста)

mov ebx, url ;URL

;проверим, чтобы начиналось с "HTTP://" или "http://"
lea edi, http
mov esi, e bx
mov ecx, 7
cmp_loop:
lodsb
xor al, [edi] ;будут равны, если 0 или 20h (одна большая, вторая маленькая)
jz cmp_next
cmp al, 20h
jne error_not_http
cmp_next:
inc edi
loop cmp_loop

add ebx, 7 ;ebx - начало имени хоста

;иниируем структуру WSAData с проверкой версии
invoke WSAStartup, 101h, addr WSAData
test eax, eax ;провера на ошибку
jnz error_no_WSA

mov edi, ebx
or ecx, -1
xor eax, eax
repne scasb
not ecx
dec ecx ;длина строки [edi]

mov esi, ebx ;чтобы не портить исходную строку, скопируем во временный буфер
lea edi, http_host ;http_host - строка с именем сервера и путем

;копируем
mov eax, ecx
shr ecx, 2
rep movsd
mov ecx, eax
and ecx, 3
rep movsb

;проверим, задан ли порт (через ':')
invoke StrChr, addr http_host, ':'
test eax, eax
je port_default ;eax = 0 - порт не задан
mov byte ptr [eax], 0 ;убере м порт из строки, "обрежем" строку в позиции ':'
inc eax ;eax - начало строки с номером порта
invoke String2Dword, eax ;преобразуем в число
mov edi, eax ;сохраним ка порт
test edi, edi ;если 0, то ставим порт по умолчанию
jne server_name
port_default:
mov edi, 80 ;порт по умолчанию

server_name: ;разберем строку на имя сервера и путь
invoke StrChr, addr http_host, '/' ;для этого ищем '/'
test eax, eax
je path_not_found ;не найдено - пути нет
mov byte ptr [eax], 0 ;уберем путь из строки, "обрежем" строку в позиции '/'
inc eax ;eax - адрес пути
jmp set_http_path
path_not_found:
lea eax, none ;адрес пустой строки
set_http_path:
mov http_path, eax ;сохраним адрес пути

;Разименуем имя хоста, получим IP в структуре hostent
invoke gethostbyname, addr http_host
mov esi, eax ;struct hostent*
test esi, esi
jz error_DNS ;если 0, то ошибка

;очистим структуру ssin
xor ecx, ecx
mov ssin.sin_family, AF_INET
mov ssin.sin_port, cx
mov dword ptr ssin.sin_zero, ecx
mov dword ptr ssin.sin_zero+4, ecx
invoke htonl, INADDR_ANY
mov ssin.sin_addr.S_un.S_addr, eax

;создаем сокет
invoke socket, AF_INET, SOCK_STREAM, 0
cmp eax, INVALID_SOCKET ;ошибка?
je error_socket
mov sock, eax ;сохраним сокет

invoke bind, sock, addr ssin, 16 ;свяжем сокет со структурой ssin

;заполним IP адрес в ssin
mov ebx, [esi.hostent].h_list
mov ebx, DWORD PTR [ebx]
mov eax, DWORD PTR [ebx]
mov ssin.sin_addr.S_un.S_addr, eax ;в структуру

;заполним порт
invoke htons, edi ;порт в порядок, принятый в Инет-е (старший первым)
mov ssin.sin_port, ax ;в структуру

;выведем сообщение о соединении
movzx ecx, byte ptr [ebx]
movzx edx, byte ptr [ebx+1]
movzx eax, byte ptr [ebx+2]
movzx ebx, byte ptr [ebx+3]
invoke wspr intf, addr query, addr Conecting, ecx, edx, eax, ebx
invoke StdOut, addr query

;соединяемся с сервером
invoke connect, sock , addr ssin, 16
cmp eax, -1
je error_connect ;ошибка

invoke StdOut, addr Ok ;выведем "Ok"

;сформируем строку запроса
invoke wsprintf, addr query, addr fquery, http_path, addr http_host
;выведем на экран
invoke StdOut, addr query
;отправим на сервер
invoke SendString, sock, addr query
test al, al
jz error_send ;ошибка?

invoke GetString, sock ;принимаем ответ,
;результат в eax (и если =0, то длина в ecx)
OU_ret:
ret
;ошибки !!!!!!!!!!!!!!!!!
error_not_http:
mov eax, 7 ;признак некорректного адреса (без http://)
jmp OU_ret
error_no_WSA:
mov eax, 1 ;не та версия WSA
jmp OU_ret
error_DNS:
mov eax, 2 ;имя не разименовано
jmp OU_ret
error_socket:
mov eax, 4 ;ошибка создания сокета
jmp OU_ret
error_connect:
mov eax, 3 ;ошибка соединения
jmp OU_ret
error_send:
mov eax, 5 ;ошибка посылки запроса
jmp OU_ret
OpenURL endp

;закрываем сокет, сбрасываем библиотеку winsock
CloseURL proc
.if sock!=0
invoke closesocket, sock
mov sock,0
.endif
jmp WSACleanup ;вернется по ret функции
CloseURL endp

;преобразование из строки в число
;думаю, в комментариях не нуждается... :)
String2Dword proc uses ecx edi edx esi String:DWORD
xor ecx,ecx
mov edi,String
invoke lstrlen,String
.while eax!=0
xor edx,edx
mov dl,byte ptr [edi]
sub dl,"0"
mov esi,eax
dec esi
push eax
mov eax,edx
push ebx
mov ebx,10
.while esi > 0
mul ebx
dec esi
.endw
pop ebx
add ecx,eax
pop eax
inc edi
dec eax
.endw
mov eax,ecx
ret
String2Dword endp

END main

-----
Удачи!

Ответ отправил: Лысков Игорь Витальевич, Модератор
Ответ отправлен: 03.06.2010, 11:41
Номер ответа: 261839
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru
Абонент Skype: igorlyskov

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 261839 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Вопрос № 178723:

    Уважаемые эксперты, подскажите, пожалуйста, как скомпилировать приведённую ниже в листинге программу. В ней пропущена только модель памяти и модель процессора? У меня не хочет даже ассемблироваться. Этот листинг я скопировал из книги Абраша «Таинства программирования графики». Сама книга на русском языке, к которой прилагалась дискета с источниками программ, написанных в книге, издавалась только раз и то в 1996 году. На русском языке книгу скачать нигде не мог, пришлось качать на английском, который еле-еле знаю. Прилагаемую к книге дискету скачать нигде не смог, иначе бы скомпилировал нормально. В книге у автора листинги всех программ начинаются без указания модели процессора и памяти. Одна моя ошибка связана со стеком: на команду stack segment para stack 'STACK' пишется Reserved word used as symbol: STACK. Несколько ошибок Offset or pointer is 32-bit и Illegal instruction. Компилировал TASM 5.0.
    В программе есть команды ifdef, else, endif – может, нужно 32-б итным MASM’ом как-то компилировать? Я пробовал и им, но тоже с ошибками

    Отправлен: 29.05.2010, 12:31
    Вопрос задал: Adsorores, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Хоменко Владимир Александрович, 1-й класс :
    Здравствуйте, Adsorores.

    вот исправленный исходник (кое где не стоит символ комментария и некоторые переменные указаны с ошибкой в синтаксисе). компилируется масм32 но для линковки exe нужно использовать досовский DOSLNK.32.
    Проверил, компиляция и сборка прошла успешно. Проверить работоспособность программы не могу т.к. моя система 64-разрядная.

    Код:
    ; Sample VGA program.
    ; Animates four balls bouncing around a playfield by using
    ; page flipping. Playfield is panned smoothly both horizontally
    ; and vertically.
    ; By Michael Abrash.
    ;
    stack segment para stack 'STACK'
    db 512 dup(?)
    stack ends
    ;
    MEDRES_VIDEO_MODE equ 0 ;define for 640x350 video mode
    ; comment out for 640x200 mode
    VIDEO_SEGMENT equ 0a000h ;display memory segment for
    ; true VGA graphics modes
    LOGICAL_SCREEN_WIDTH equ 672/8 ;width in bytes and height in
    ; scan
    LOGICAL_SCREEN_HEIGHT equ 384 ; lines of the virtual screen
    ; we'll work with
    PAGE0 equ 0 ;flag for page 0 when page flipping
    PAGE1 equ 1 ;flag for page 1 when page flipping
    PAGE0_OFFSET equ 0 ;start offset of page 0 in VGA memory
    PAGE1_OFFSET equ LOGICAL_SCREEN_WIDTH * LOGICAL_SCREEN_HEIGHT
    ;start offset of page 1 (both pages
    ; are 672x384 virtual screens)
    BALL_WIDTH equ 24/8 ;width of ball in display memory bytes
    BALL_HEIGHT equ 24 ;he ight of ball in scan lines
    BLANK_OFFSET equ PAGE1_OFFSET * 2 ;start of blank image
    ; in VGA memory
    BALL_OFFSET equ BLANK_OFFSET + (BALL_WIDTH * BALL_HEIGHT)
    ;start offset of ball image in VGA memory
    NUM_BALLS equ 4 ;number of balls to animate
    ;
    ; VGA register equates.
    ;
    SC_INDEX equ 3c4h ;SC index register
    MAP_MASK equ 2 ;SC map mask register
    GC_INDEX equ 3ceh ;GC index register
    GC_MODE equ 5 ;GC mode register
    CRTC_INDEX equ 03d4h ;CRTC index register
    START_ADDRESS_HIGH equ 0ch ;CRTC start address high byte
    START_ADDRESS_LOW equ 0dh ;CRTC start address low byte
    CRTC_OFFSET equ 13h ;CRTC offset register
    INPUT_STATUS_1 equ 03dah ;VGA status register
    VSYNC_MASK equ 08h ;vertical sync bit in sta tus register 1
    DE_MASK equ 01h ;display enable bit in status register 1
    AC_INDEX equ 03c0h ;AC index register
    HPELPAN equ 20h OR 13h ;AC horizontal pel panning register
    ; (bit 7 is high to keep palette RAM
    ; addressing on)
    dseg segment para common 'DATA'
    CurrentPage db PAGE1 ;page to draw to
    CurrentPageOffset dw PAGE1_OFFSET
    ;
    ; Four plane's worth of multicolored ball image.
    ;
    BallPlane0Image label byte ;blue plane image
    db 000h, 03ch, 000h, 001h, 0ffh, 080h
    db 007h, 0ffh, 0e0h, 00fh, 0ffh, 0f0h
    db 4 * 3 dup(000h)
    db 07fh, 0ffh, 0feh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh
    db 4 * 3 dup(000h)
    db 07fh, 0ffh, 0feh, 03fh, 0ffh, 0fch
    db 03fh, 0ffh, 0fch, 01fh, 0ffh, 0f8h
    db 4 * 3 dup(000h)
    BallPlane1Image label byte ;green plan e image
    db 4 * 3 dup(000h)
    db 01fh, 0ffh, 0f8h, 03fh, 0ffh, 0fch
    db 03fh, 0ffh, 0fch, 07fh, 0ffh, 0feh
    db 07fh, 0ffh, 0feh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh
    db 8 * 3 dup(000h)
    db 00fh, 0ffh, 0f0h, 007h, 0ffh, 0e0h
    db 001h, 0ffh, 080h, 000h, 03ch, 000h
    BallPlane2Image label byte ;red plane image
    db 12 * 3 dup(000h)
    db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 07fh, 0ffh, 0feh
    db 07fh, 0ffh, 0feh, 03fh, 0ffh, 0fch
    db 03fh, 0ffh, 0fch, 01fh, 0ffh, 0f8h
    db 00fh, 0ffh, 0f0h, 007h, 0ffh, 0e0h
    db 001h, 0ffh, 080h, 000h, 03ch, 000h
    BallPlane3Image label byte ;intensity on for all planes,
    ; to produce high-intensity
    ; colors
    db 000h, 03ch, 000h, 001h, 0ffh, 080h
    db 007h, 0ffh, 0e0h, 00fh, 0ffh, 0f0h
    db 01fh, 0ffh, 0f8h, 03fh, 0ffh, 0fch
    db 03fh, 0ffh, 0fch, 07fh, 0ffh, 0feh
    db 07fh, 0ffh, 0feh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh
    db 0ffh, 0ffh, 0ffh, 07fh, 0ffh, 0feh
    db 07fh, 0ffh, 0feh, 03fh, 0ffh, 0fch
    db 03fh, 0ffh, 0fch, 01fh, 0ffh, 0f8h
    db 00fh, 0ffh, 0f0h, 007h, 0ffh, 0e0h
    db 001h, 0ffh, 080h, 000h, 03ch, 000h
    ;
    BallX dw 15, 50, 40, 70 ;array of ball x coords
    BallY dw 40, 200, 110, 300 ;array of ball y coords
    LastBallX dw 15, 50, 40, 70 ;previous ball x coords
    LastBallY dw 40, 100, 160, 30 ;previous ball y coords
    Ball XInc dw 1, 1, 1, 1 ;x move factors for ball
    BallYInc dw 8, 8, 8, 8 ;y move factors for ball
    BallRep dw 1, 1, 1, 1 ;# times to keep moving
    ; ball according to
    ; current
    ; increments
    BallControl dw Ball0Control, Ball1Control ;pointers to
    ; current
    dw Ball2Control, Ball3Control ; locations in
    ; ball
    ; control strings
    BallControlString dw Ball0Control, Ball1Control ;pointers to
    dw Ball2Control, Ball3Control ; start of ball
    ; control strin gs
    ;
    ; Ball control strings.
    ;
    Ball0Control label word
    dw 10, 1, 4, 10, -1, 4, 10, -1, -4, 10, 1, -4, 0
    Ball1Control label word
    dw 12, -1, 1, 28, -1, -1, 12, 1, -1, 28, 1, 1, 0
    Ball2Control label word
    dw 20, 0, -1, 40, 0, 1, 20, 0, -1, 0
    Ball3Control label word
    dw 8, 1, 0, 52, -1, 0, 44, 1, 0, 0
    ;
    ; Panning control string.
    ;
    ifdef MEDRES_VIDEO_MODE
    PanningControlString dw 32, 1, 0, 34, 0, 1, 32, -1, 0, 34, 0, -1, 0
    else
    PanningControlString dw 32, 1, 0, 184, 0, 1, 32, -1, 0, 184, 0,
    -1, 0
    endif
    PanningControl dw PanningControlString ;pointer to current
    ; location
    ; in panning control
    ; string
    PanningRep dw 1 ;# times to pan accord ing to current
    ; panning increments
    PanningXInc dw 1 ;x panning factor
    PanningYInc dw 0 ;y panning factor
    HPan db 0 ;horizontal pel panning setting
    PanningStartOffset dw 0 ;start offset adjustment to produce
    ; vertical
    ; panning & coarse horizontal panning
    dseg ends
    ;
    ; Macro to set indexed register P2 of chip with index register
    ; at P1 to AL.
    ;
    SETREG macro P1, P2
    mov dx,P1
    mov ah,al
    mov al,P2
    out dx,ax
    endm
    ;
    cseg segment para public 'CODE'
    assume cs:cseg, ds:dseg
    start proc near
    mov ax,dseg
    mov ds,ax
    ;
    ; Select graphics mode.
    ;
    ifdef MEDRES_VIDEO_MODE
    mov ax,010h
    else
    mov ax,0eh
    endif
    int 10h
    ;
    ; ES always points to VGA memory.
    ;
    mov ax,VIDEO_SEGMENT
    mov es,ax
    ;
    ; Draw border around playfield in both pages.
    ;
    mov di,PAGE0_OFFSET
    call DrawBorder ;page 0 border
    mov di,PAGE1_OFFSET
    call DrawBorder ;page 1 border
    ;
    ; Draw all four plane's worth of the ball to undisplayed VGA memory.
    ;
    mov al,01h ;enable plane 0
    SETREG SC_INDEX, MAP_MASK
    mov si,offset BallPlane0Image
    mov di,BALL_OFFSET
    mov cx,BALL_WIDTH * BALL_HEIGHT
    rep movsb
    mov al,02h ;enable plane 1
    SETREG SC_INDEX, MAP_MASK
    mov si,offset BallPlane1Image
    mov di,BALL_OFFSET
    mov cx,BALL_WIDTH * BALL_HEIGHT
    rep movsb
    mov al,04h ;enable plane 2
    SETREG SC_INDEX, MAP_MASK
    mov si,offset BallPlane2Image
    mov di,BALL_OFFSET
    mov cx,BALL_WIDTH * BALL_HEIGHT
    rep movsb
    mov al,08h ;enable plane 3
    SETREG SC_INDEX, MAP_MASK
    mov si,offset BallPlane3Image
    mov di,BALL_OFFSET
    mov cx,BALL_WIDTH * BALL_HEIGHT
    rep movsb
    ;
    ; Draw a blank image the size of the ball to undisplayed VGA memory.
    ;
    mov al,0fh ;enable all memory planes, since
    ; the
    SETREG SC_INDEX, MAP_MASK ; blank has to erase all planes
    mov di,BLANK_OFFSET
    mov cx,BALL_WIDTH * BALL_HEIGHT
    sub al,al
    rep stosb
    ;
    ; Set VGA to write mode 1, for block copying ball and blank images.
    ;
    mov dx,GC_INDEX
    mov al,GC_MODE
    out dx,al ;point GC Index to GC Mode register
    inc dx ;point to GC Data register
    jmp $+2 ;delay to let bus settl e
    in al,dx ;get current state of GC Mode
    and al,not 3 ;clear the write mode bits
    or al,1 ;set the write mode field to 1
    jmp $+2 ;delay to let bus settle
    out dx,al
    ;
    ; Set VGA offset register in words to define logical screen width.
    ;
    mov al,LOGICAL_SCREEN_WIDTH / 2
    SETREG CRTC_INDEX, CRTC_OFFSET
    ;
    ; Move the balls by erasing each ball, moving it, and
    ; redrawing it, then switching pages when they're all moved.
    ;
    BallAnimationLoop:
    mov bx,( NUM_BALLS * 2 ) - 2
    EachBallLoop:
    ;
    ; Erase old image of ball in this page (at location from one more
    ; earlier).
    ;
    mov si,BLANK_OFFSET ;point to blank image
    mov cx,[LastBallX+bx]
    mov dx,[LastBallY+bx]
    call DrawBall
    ;
    ; Set new last ball location.
    ;
    mov ax,[B allX+bx]
    mov [LastBallX+bx],ax
    mov ax,[BallY+bx]
    mov [LastBallX+bx],ax
    ;
    ; Change the b all movement values if it's time to do so.
    ;
    dec [BallRep+bx] ;has current repeat factor
    ; run out?
    jnz MoveBall
    mov si,[BallControl+bx] ;it's time to change movement
    ; values
    lodsw ;get new repeat factor from
    ; control string
    and ax,ax ;at end of control string?
    jnz SetNewMove
    mov si,[BallControlString+bx] ;reset control string
    lodsw ;get new repeat factor
    SetNewMove:
    mov [BallRep+bx],ax ;set new movement repeat factor
    lodsw ;set new x movement increment
    mov [BallXInc+bx],ax
    lodsw ;set new y movement increment
    mov [BallYInc+bx],ax
    mov [BallControl+bx],si ;save new control string pointer
    ;
    ; Move the ball.
    ;
    MoveBall:
    mov ax,[BallXInc+bx]
    add [BallX+bx],ax ;move in x direction
    mov ax,[BallYInc+bx]
    add [BallY+bx],ax ;move in y direction
    ;
    ; Draw ball at new location.
    ;
    mov si,BALL_OFFSET ;point to ball's image
    mov cx,[BallX+bx]
    mov dx,[BallY+bx]
    call DrawBall
    ;
    dec bx
    dec bx
    jns EachBallLoop

    ;
    ; Set up the next panning state (but don't program it into the
    ; VGA yet).
    ;
    call AdjustPanning

    ;
    ; Wait for display enable (pixel data being displayed) so we know
    ; we're nowhere near vertical sync, where the start address gets
    ; latched and used.
    ;
    call WaitDisplayEnable
    ;
    ; Flip to the new page by changing the start address.
    ;
    mov ax,[CurrentPageOffset]
    add ax,[PanningStartOffset]
    push ax
    SETREG CRTC_INDEX, START_ADDRESS_LOW
    mov al,byte ptr [CurrentPageOffset+1]
    pop ax
    mov al,ah
    SETREG CRTC_INDEX, START_ADDRESS_HIGH
    ;
    ; Wait for vertical sync so the new start address has a chance
    ; to take effect.
    ;
    call WaitVSync
    ;
    ; Set horizontal panning now, just as new start address takes effect.
    ;
    mov al,[HPan]
    mov dx,INPUT_STATUS_1
    in al,dx ;reset AC addressing to index
    ; reg
    mov dx,AC_INDEX
    mov al,HPELPAN
    out dx,al ;set AC index to pel pan reg
    mov al,[HPan]
    out dx,al ;set new pel panning
    ;
    ; Flip the page to draw to to the undisplayed page.
    ;
    xor [CurrentPage],1
    jnz IsPage1
    mov [CurrentPageOffset],PAGE0_OFFSET
    jmp short EndFlipPage
    IsPage1:
    mov [CurrentPageOffset],PAGE1_OFFSET
    EndFlipPage:
    ;
    ; Exit if a key's been hit.
    ;
    mov ah,1
    int 16h
    jnz Done
    jmp BallAnimationLoop
    ;
    ; Finished, clear key, reset screen mode and exit.
    ;
    Done:
    mov ah,0 ;clear key
    int 16h
    ;
    mov ax,3 ;reset to text mode
    int 10h
    ;
    mov ah,4ch ;exit to DOS
    int 21h
    ;
    start endp
    ;
    ; Routine to draw a ball-sized image to all planes, copying from
    ; offset SI in VGA memory to offset CX,DX (x,y) in VGA memory in
    ; the current page.
    ;
    DrawBall proc near
    mov ax,LOGICAL_SCREEN_WIDTH
    mu l dx ;offset of start of top image scan line
    add ax,cx ;offset of upper left of image
    add ax,[Cur rentPageOffset] ;offset of start of page
    mov di,ax
    mov bp,BALL_HEIGHT
    push ds
    push es
    pop ds ;move from VGA memory to VGA memory
    DrawBallLoop:
    push di
    mov cx,BALL_WIDTH
    rep movsb ;draw a scan line of image
    pop di
    add di,LOGICAL_SCREEN_WIDTH ;point to next destination scan
    ;line
    dec bp
    jnz DrawBallLoop
    pop ds
    ret
    DrawBall endp
    ;
    ; Wait for the leading edge of vertical sync pulse.
    ;
    WaitVSync proc near
    mov dx,INPUT_STATUS_1
    WaitNotVSyncLoop:
    in al,dx
    and al,VSYNC_MASK
    jnz WaitNotVSyncLoop
    WaitVSyncLoop:
    in al,dx
    and al,VSYNC_MASK
    jz WaitVSyncLoop
    ret
    WaitVSync end p

    ;
    ; Wait for display enable to happen (pixels to be scanned to
    ; the screen, indicating we're in the middle of displaying a frame).
    ;
    WaitDisplayEnable proc near
    mov dx,INPUT_STATUS_1
    WaitDELoop:
    in al,dx
    and al,DE_MASK
    jnz WaitDELoop
    ret
    WaitDisplayEnable endp

    ;
    ; Perform horizontal/vertical panning.
    ;
    AdjustPanning proc near
    dec [PanningRep] ;time to get new panning values?
    jnz DoPan
    mov si,[PanningControl] ;point to current location in
    ; panning control string
    lodsw ;get panning repeat factor
    and ax,ax ;at end of panning control
    ;string?
    jnz SetNewPanValues
    mov si,offset PanningControlString ;reset to start of
    ;string
    lodsw ;get panning repeat factor
    SetNewPanValues:
    mov [PanningRep],ax ;set new panning repeat value
    lodsw
    mov [PanningXInc],ax ;horizontal panning value
    lodsw
    mov [PanningYInc],ax ;vertical panning value
    mov [PanningControl],si ;save current location in panning
    ; control string
    ;
    ; Pan according to panning values.
    ;
    DoPan:
    mov ax,[PanningXInc] ;horizontal panning
    and ax,ax
    js PanLeft ;negative means pan left
    jz CheckVerticalPan
    mov al,[HPan]
    inc al ;pan right; if pel pan reaches
    cmp al,8 ; 8, it's time to move to the
    jb SetHPan ; next byte with a pel pan of 0
    sub al,al ; and a start offset that's one
    inc [PanningStartOffset] ; higher
    jmp short SetHPan
    PanLeft:
    mov al,[HPan]
    dec al ;pan left; if pel pan reaches
    ;-1,
    jns SetHPan ; it's time to move to the next
    mov al,7 ; byte with a pel pan of 7 and a
    dec [PanningStartOffset] ; start offset that's one lower
    SetHPan:
    mov [HPan],al ;save new pel pan value
    CheckVerticalPan:
    mov ax,[PanningYInc] ;vertical panning
    and ax,ax
    js PanUp ;negative means pan up
    jz EndPan
    add [PanningStartOffset],LOGICAL_SCREEN_WIDTH
    ;pan down by advancing the start
    ; address by a scan line
    jmp short EndPan
    Pa nUp:
    sub [PanningStartOffset],LOGICAL_SCREEN_WIDTH
    ;pan up by retarding the start
    ; address by a scan line
    EndPan:
    ret
    ;
    ; Draw textured border around playfield that starts at DI.
    ;
    DrawBorder proc near
    ;
    ; Draw the left border.
    ;
    push di
    mov cx,LOGICAL_SCREEN_HEIGHT / 16
    DrawLeftBorderLoop:
    mov al,0ch ;select red color for block
    call DrawBorderBlock
    add di,LOGICAL_SCREEN_WIDTH * 8
    mov al,0eh ;select yellow color for block
    call DrawBorderBlock
    add di,LOGICAL_SCREEN_WIDTH * 8
    loop DrawLeftBorderLoop
    pop di
    ;
    ; Draw the right border.
    ;
    push di
    add di,LOGICAL_SCREEN_WIDTH - 1
    mov cx,LOGICAL_SCREEN_HEIGHT / 16
    DrawRight BorderLoop:
    mov al,0eh ;select yellow color for block
    call DrawBorderBlock
    add di,LOGICAL_SCREEN_WIDTH * 8
    mov al,0ch ;select red color for block
    call DrawBorderBlock
    add di,LOGICAL_SCREEN_WIDTH * 8
    loop DrawRightBorderLoop
    pop di
    ;
    ; Draw the top border.
    ;
    push di
    mov cx,(LOGICAL_SCREEN_WIDTH - 2) / 2
    DrawTopBorderLoop:
    inc di
    mov al,0eh ;select yellow color for block
    call DrawBorderBlock
    inc di
    mov al,0ch ;select red color for block
    call DrawBorderBlock
    loop DrawTopBorderLoop
    pop di
    ;
    ; Draw the bottom border.
    ;
    add di,(LOGICAL_SCREEN_HEIGHT - 8) * LOGICAL_SCREEN_WIDTH
    mov cx,(LOGICAL_SCREEN_WIDTH - 2) / 2
    DrawBottomBorderLoop :
    inc di
    mov al,0ch ;select red color for block
    call DrawBorderBlock
    inc di
    mov al,0eh ;select yellow color for block
    call DrawBorderBlock
    loop DrawBottomBorderLoop
    ret
    DrawBorder endp
    ;
    ; Draws an 8x8 border block in color in AL at location DI.
    ; DI preserved.
    ;
    DrawBorderBlock proc near
    push di
    SETREG SC_INDEX, MAP_MASK
    mov al,0ffh
    rept 8
    stosb
    add di,LOGICAL_SCREEN_WIDTH - 1
    endm
    pop di
    ret
    DrawBorderBlock endp
    AdjustPanning endp
    cseg ends
    end start
    Оформил программу тегом [code]
    -----
    ∙ Отредактировал: Лысков Игорь Витальевич, Модератор
    ∙ Дата редактирования: 29.05.2010, 21:35 (время московское)

    Ответ отправил: Хоменко Владимир Александрович, 1-й класс
    Ответ отправлен: 29.05.2010, 15:04
    Номер ответа: 261744

    Оценка ответа: 5

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 261744 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.16 от 26.05.2010

    В избранное