Search code examples
assemblygame-developmentx86-16bioslow-level-code

Why is the pixel not showing when i turn its position into variables ? Assembly 8086 NASM


Im trying to make a ball with Assembly 8086 NASM using the INT 10H and DOSBOX, in UBUNTU

like this :

 MOV AH, 0Ch ; function to write the pixel
 MOV AL, 0Fh ; color of the pixel (set to white)
 MOV BH, 00h ; the page number (0 because its the only page im working on)
 MOV CX, 160 ; X Position on the screen
 MOV DX, 100 ; Y Position on the screen
 INT 10h

Im working on a 360x200 video mode, so the pixel shows up at the middle here is how its working : https://imgur.com/BS62ohp

When i assign the values directly to CX and DX (x and y positions), the pixel shows up pretty fine once i turn it into an initialized variable, it disappear and the screen is completely black. No bugs no warnings whatsoever here is it turned into variables :

segment .data
  BALL_X DW 160
  BALL_Y DW 100

segment .text
  global main

main:
  MOV AH, 0Ch
  MOV AL, 0Fh
  MOV BH, 00h
  **MOV CX, [BALL_X]**
  **MOV DX, [BALL_Y]**
  INT 10h

i have tried "[BALL_X]", "word [BALL_X]", "BALL_X". here is when i turn it into variables : https://imgur.com/6jXqoaq

Here is the full code :

segment .data
  BALL_X DW 300
  BALL_Y DW 170

segment .text
  global main

main:
  ; setting the video mode to 360x200
  MOV AH, 00h
  MOV Al, 13h
  INT 10h
  
  ; setting the background color to Black
  MOV AH, 0Bh
  MOV BH, 00h
  MOV BL, 0h
  INT 10h

  ; the pixel code
  MOV AH, 0Ch
  MOV AL, 0Fh
  MOV BH, 00h
  MOV CX, word [BALL_X]
  MOV DX, word [BALL_Y]
  INT 10h

Solution

  • COM programs use "tiny" memory model: text, data and stack are in the same segment. Code starts at offset 100h. You need to specify this offset with org directive at the beginning of file:

    org 100h
    ...
    

    But it's much faster to draw directly to video memory instead of drawing with int 10h service:

    org 100h
    cpu 186 ; for one-instruction shifts
    
    main:
        ; setting the video mode to 320x200
        mov ax, 0013h
        int 10h
    
        ; ES points to video memory
        mov ax, 0A000h
        mov es, ax
    
        ; setting the background color to Black
        ; fill memory area with 0
        xor ax, ax
        xor di, di
        mov cx, 320*200/2
        cld
        rep stosw
    
        ; the pixel code
        mov ax, word [BALL_Y]
        shl ax, 6                   ; ax = BALL_Y * 64
        mov bx, ax
        shl ax, 2                   ; ax = BALL_Y * 4 * 64 = BALL_Y * 256
        add bx, ax                  ; bx = BALL_Y * 64 + BALL_Y * 256 = BALL_Y * 320
        add bx, word [BALL_X]       ; bx = BALL_Y * 320 + BALL_X
    
        mov byte es:[bx], 0Fh       ; draw white pixel
    
        mov ah, 0                   ; wait for key
        int 16h
        mov ax, 0003h               ; return to 80x25 text mode
        int 10h
        mov ax, 4C00h               ; exit to DOS
        int 21h
    
    BALL_X DW 300
    BALL_Y DW 170