codefordumm!ies: the cool logo

J'apprends la programmation avec l'assembleur x86, partie 8

en développement !

piou! piou!

Le code source de invaders.asm

; ========
; invaders
; ========
;
; C:\nasm -fbin invaders.asm -o invaders.com    

org 0x100

global main

VGA_MEMORY_SEGMENT  equ 0xa000  ; segment mémoire de la carte VGA
VGA_WIDTH       equ 320     ; nombre de pixels horizontaux en VGA
VGA_HEIGHT      equ 200     ; nombre de pixels verticaux en VGA

section .text

main:
  call enter_vga    ; on entre dans le mode VGA
  call render       ; on dessine un truc
  call wait_key     ; on attend une touche au clavier
  call quit_vga     ; on quitte le mode VGA

  mov ax, 0x4c00    ; on quitte sans erreur
  int 0x21

enter_vga:
  mov ah, 0x0f      ; on récupère le mode vidéo en cours
  int 0x10      ; dans al
  mov [old_mode], al    ; on conserve cette valeur dans old_mode

  mov ah, 0x00      ; on change le mode vidéo
  mov al, 0x13      ; AL = 0x13 soit VGA 320x200x256 couleurs
  int 0x10
  ret

quit_vga:
  mov ah, 0x00      ; on restaure le mode vidéo 
  mov al, [old_mode]    ; conservé dans old_mode
  int 0x10
  ret

wait_key:
  mov ah, 0x01      ; on vérifie si une touche a été appuyée
  int 0x16
  jz wait_key       ; si ZF est activé, aucune touche n'a été appuyée
  ret

render:
  mov ax, VGA_MEMORY_SEGMENT
  mov es, ax

  xor dx, dx            ; dx est l'index du sprite, soit 0
  mov [sprite_id], dx
  mov ax, 146           ; x = 146
  mov [x], ax
  mov ax, 92            ; y = 92
  mov [y], ax
  mov al, 4             ; clr = rouge
  mov [clr], al
  call draw_sprite      ; on dessine le premier sprite

  inc dx                ; dx est l'index du second sprite
  mov [sprite_id], dx
  mov ax, [x]           ; x = x + 16
  add ax, 16
  mov [x], ax
  mov al, 2             ; clr vert
  mov [clr], al
  call draw_sprite      ; on dessine le second sprite

  ret

put_pixel:
  push ax
  push dx
  push di

  mov ax, VGA_WIDTH     ; ax = 320
  mov dx, [y]           ; dx = y
  mul dx        ; dx:ax = 320 * y
  mov di, ax            ; di = 320 * y
  add di, [x]           ; di = 320 * y + x
  mov al, [clr]         ; al = clr
  stosb                 ; [es:di] = clr

  pop di
  pop dx
  pop ax
  ret

draw_sprite:
  pusha                 ; on sauve tous les registres courants

  mov ax, [y]           ; on sauve y
  push ax
  mov ax, [x]           ; on sauve x
  push ax
  mov [prevx], ax         

  mov ax, [sprite_id]   ; ax = sprite_id
  shl ax, 4             ; ax = sprite_id * 16: il y a 16 bytes par sprites
  mov si, sprite1       ; si est l'offset du premier sprite
  add si, ax            ; on ajoute à si l'offset du sprite choisi par sprite_id

  mov cl, 8             ; compteur ligne : 8 lignes par sprites
draw_sprite_line:
  lodsw                 ; ax = [ds:si] = ligne du sprite
  mov dx, [x]           ; dx = x
  mov bx, 0x8000        ; notre masque
  mov ch, 16            ; compteur bit : 16 bits par lignes
draw_sprite_bit:
  test bx, ax           ; test bit & masque
  jz draw_sprite_no_pixel   ; si 0 on ne dessine rien, sinon...
  call put_pixel        ; ... on dessine le pixel
draw_sprite_no_pixel:
  shr bx, 1             ; masque pour le bit suivant
  inc dx                ; x = x + 1
  mov [x], dx               
  dec ch                ; on passe au  bit suivant  
  jnz draw_sprite_bit

  push ax               ; on conserve ax qui va nous servir pour affecter les variables
  mov ax, [y]           ; y = y + 1
  inc ax
  mov [y], ax               
  mov ax, [prevx]       ; on recupère la valeur de x
  mov [x], ax
  pop ax                ; on récupère ax
  dec cl                ; on passe à la ligne suivante
  jnz draw_sprite_line

  pop ax                ; on restaure x
  mov [x], ax
  pop ax                ; on restaure y
  mov [y], ax         

  popa                  ; on restaure tous les registres courants
  ret

section .data
old_mode: db 0          ; variable pour conserver le mode vidéo précédent
x: dw 0                 ; x du pixel    
prevx: dw 0             ; prevx pour conserver x dans notre boucle
y: dw 0                 ; y du pixel
clr: db 0               ; couleur du pixel
sprite_id: dw 0         ; index du sprite (0 ou 1)  
; ci dessous les lignes des deux sprites :
sprite1: dw 0x0820, 0x0440, 0x0fe0, 0x1bb0, 0x3ff8, 0x2fe8, 0x2828, 0x06c0
sprite2: dw 0x0300, 0x0780, 0x0fc0, 0x1b60, 0x1fe0, 0x0480, 0x0b40, 0x14a0

Pour m'entrainer

Solution