2011-07-03 2 views
2

J'essaie de faire la vidéo double buffer en assembleur, mais dans ce cas j'ai un problème, je ne sais pas comment le résoudre, il ne peut pas se fermer après avoir appuyé sur une touche . Apparemment, le problème est dans inc di:double buffer video en assembleur

(je suis en train de peindre tous les 320 * 200 pixels avec la couleur blanche avec un tampon)

.model small 
.386 
.stack 400h 
.data 

modovideo db ? 
vram dw 0 

xVal dw ? 
yVal dw ? 

.code 
main proc 
    mov ax,@data 
    mov ds,ax 

    mov ah,0fh 
    int 10h 
    mov modovideo,al 

    mov ah,0 
    mov al,13h 
    int 10h 

    ; Segmento de memoria ===================================== 

    mov ah,48h 
    mov bx,4000 ; 64000/16 
    int 21h 
    mov vram,ax 

    ; Escribir en el segmento de memoria ======================================= 

mov es,vram 

;offset = 320*y + x 
    ;mov xVal,160 
    ;mov yVal,100 
    ;mov ax,320 
    ;mul yVal 
    ;add ax,xVal 


mov di,0 
mov al,7 

mov cx,640 
paso1: 
    mov es:[di],al 
    inc di ; <----------- 
    loop paso1 

; Volcar sobre pantalla ====================================================== 

mov ds,vram 
xor si,si 
mov dx,0A000h 
mov es,dx 
xor di,di 
mov cx,64000 
rep movsb 

mov ah,1 
int 21h 

salir: 
mov al,modovideo 
mov ah,0 
int 10h 

mov ah,4ch 
int 21h 

    main endp 
+0

Que voulez-vous dire le problème est avec 'inc di'? Cela fonctionne-t-il si vous le commentez? BTW: Ce n'est probablement pas ce qui cause vos problèmes, mais vous devriez effacer l'indicateur de direction (avec 'cld') avant d'utiliser' movsb'. – user786653

Répondre

2

Quelques choses:

  • Vérifiez la valeur de retour lorsque vous allouez de la mémoire (carry est réglé sur erreur, ax contient le code d'erreur, avec 8 signifie mémoire insuffisante) [Notez que si vous utilisez un fichier COM, la plus grande partie de la mémoire disponible sera déjà allouée votre programme et donc l'allocation sera échec]
  • Vous devez effacer/définir l'indicateur de direction avant d'utiliser les instructions de chaîne (cld dans ce cas, voir par ex. Après la suppression ds de la copie, vous devez la restaurer avant d'accéder à modovideo (elle utilise implicitement ds).

Avec ces changements (et quelques-uns supplémentaires pour le faire fonctionner dans un fichier COM), cela devrait fonctionner. J'ai utilisé nasm (compiler avec) et DOSBox pour le tester. Notez que la méthode que j'utilise pour allouer de la mémoire est probablement buggée car cela fait longtemps que je n'ai pas programmé pour DOS.

 
    org 0x100 

start: 
    ; Allocate back buffer 
%if 0 
    ; Use 21h call to allocate memory (for EXE files) 
    mov ah, 0x48 
    mov bx, 64000/16 
    int 0x21 
    jc error ; carry set on error 
    mov [vscr_seg], ax 
%else 
    ; COM files get (most/all) available memory, grab some of it 
    mov bx, word [0x0002] ; Get last paragraph from PSP 
    sub bx, 64000/16 ; Make room for back buffer 
    mov [vscr_seg], bx 

    mov ax, ds 
    add ax, 0x1000 ; Program start paragraph + 64K (max of COM file) 
    cmp ax, bx ; Did it fit? 
    jae error 
%endif 
    ; Clear back buffer 
    mov es, [vscr_seg] 
    xor di, di 
    xor ax, ax 
    mov cx, 32000 
    cld 
    rep stosw 


    ; Get previous video mode 
    mov ah, 0x0f 
    int 0x10 
    mov [previous_video_mode], al 

    ; Set mode 13h (320x200 256 colors) 
    mov ax, 0x0013 
    int 0x10 

    ; Fill half the back buffer with color 15 
    mov es, [vscr_seg] 
    xor di, di 
    mov ax, 0x0f0f 
    mov cx, 16000 
    cld 
    rep stosw 

    ; And fill in all pixel colors at bottom row 
    mov di, 199 * 320 
    mov cx, 255 
    xor al, al 
.fill: 
    ; the below two instructions are equal to stosb when the direction flag is cleared 
    mov [es:di], al 
    inc di 

    inc al 
    loop .fill 

    ; Copy from back buffer to the screen 
    push ds ; Remember to save DS! 
    mov ds, [vscr_seg] 
    mov ax, 0xa000 
    mov es, ax 
    xor di, di 
    xor si, si 
    mov cx, 32000 
    cld 
    rep movsw 
    pop ds ; ... And restore it again 

    ; Wait for keypress 
    mov ah, 0x01 
    int 0x21 

    ; Restore video mode 
    mov ah, 0x00 
    mov al, [previous_video_mode] 
    int 0x10 

    ; Skip error block 
    jmp exit 

error: 
    ; Print bx and ax to facilitate debugging 
    push ax 
    call print_hex_word 
    pop ax 
    mov bx, ax 
    call print_hex_word 

    mov ah, 0x09 
    mov dx, error_string 
    int 0x21 

exit: 
    ; Exit 
    mov ax, 0x4c00 
    int 0x21 

; Print 16-bit word in BX, trashes AX and DX (at least) 
print_hex_word: 
    mov dx, bx 
    shr dx, 12 
    call print_hex_digit 
    mov dl, bh 
    call print_hex_digit 
    mov dl, bl 
    shr dl, 4 
    call print_hex_digit 
    mov dl, bl 
    call print_hex_digit 
    ; New line 
    mov ah, 0x02 
    mov dl, 13 
    int 0x21 
    mov dl, 10 
    int 0x21 
    ret 

print_hex_digit: 
    push bx 
    and dl, 0x0f 
    add dl, '0' 
    cmp dl, '9' 
    jle .print 
    add dl, 'A' - '0' - 10 
.print: 
    mov ah, 0x02 
    int 0x21 
    pop bx 
    ret 


previous_video_mode db 0 
vscr_seg dw 0 
error_string db 'Error occurred!', 13, 10, 7, '$'