2

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
Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • 2
    Looks like you didn't initialize `ds` with data segment. – dimich Jun 04 '23 at 13:54
  • What commands are you using to build and run this code? For instance, are you building a .COM or a .EXE? If a .COM, the problem is that execution starts at the first address, which contains data instead of code. If a .EXE then you have to initialize `ds`. – Nate Eldredge Jun 04 '23 at 14:29
  • Unrelated (to the problem) but are you sure about "setting the video mode to 3**6**0x200". Normally mode 13h is 3**2**0x200. – Sep Roland Jun 04 '23 at 14:33
  • (160,100) would be the midpoint of 320x200 so the 360 is probably just a typo in the post. – Nate Eldredge Jun 04 '23 at 14:35
  • @NateEldredge im indeed building a .COM using "nasm -f bin pong.asm -o pong.com" command. but i didnt quite understand can you please elaborate? i could provide more details if needed – haroun AGSOUS Jun 04 '23 at 14:37
  • @SepRoland yes my bad, 13H is 320x200 – haroun AGSOUS Jun 04 '23 at 14:38
  • @dimich i searched and found that in NASM the DS is automatically initialized with the data segment, but i might have understood wrong. if there is any way to explicitly initialize the DS with the data segment in NASM can you tell me how or where could i search more about it ? – haroun AGSOUS Jun 04 '23 at 14:53
  • Oh, never mind about my previous comment, it looks like nasm automatically takes care of moving the data section to the end. – Nate Eldredge Jun 04 '23 at 14:59
  • One other issue though is that assembly programs don't just "end". After your last int 10h executes, the machine will go on to execute whatever bytes come next in memory, which may do something unpredictable. You want to follow it with a DOS system call to exit the program. Or, for testing purposes, an infinite loop. – Nate Eldredge Jun 04 '23 at 15:01
  • @NateEldredge i added a 21h interruption to exit the program, but there is this big C:\> showing up (https://imgur.com/dDYVW3F). i think it should keep running as long as the game isnt over (future game i would say hehe) Also, the problem is still there even with the exit call, the pixel shows up normally when the values are assigned directly and not when turned into variables, just with a big C on the corner – haroun AGSOUS Jun 04 '23 at 15:15
  • So try an infinite loop instead. – Nate Eldredge Jun 04 '23 at 15:16
  • @NateEldredge i did, that C:\> is gone but the problem persists – haroun AGSOUS Jun 04 '23 at 15:22
  • @dimich Hi, sorry im new to stack overflow and i couldnt figure out how to DM you, first of all thanks for your help, it worked i just added the "org 100h". Also, this "drawing directly to video memory" seems interseting, do you have by any chance some ressources where i can learn more about it ? – haroun AGSOUS Jun 04 '23 at 16:18
  • @harounAGSOUS In mode 13h each pixel is represented by one byte in video memory Video memory stars at 0A000h:0000h. Plotting a pixel comes down to writting a byte to address `[Y * line_width + X]` where line_width is 320. You can start learning with reading external links from [Wikipedia article](https://en.wikipedia.org/wiki/Mode_13h#External_links) – dimich Jun 04 '23 at 16:55

1 Answers1

3

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
dimich
  • 1,305
  • 1
  • 5
  • 7