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, '$'
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