0

I have been playing around a bit with NASM assembly and directly working with the BIOS from the boot sector but I'm not able to define a variable like I'd usually do with NASM.

When I try to define and use a variable like usually

BALL_X dw 0x140
BALL_Y dw 0xF0

[...]

mov cx, [BALL_X]
mov dx, [BALL_Y]

it just doesn't seem to return/contain any value, though the assembler doesn't complain either when assembling it. I've also tried it with and without the section .data and section .text but that doesn't seem to change anything either. The only way I've got it to work is by manually assigning a name to an address and then assigning the values separately

BALL_X equ $
BALL_Y equ $

[...]

mov word[BALL_X], 0x140
mov word[BALL_Y], 0xF0

I've been searching for a solution on the internet but I'm struggling to find anything about how to get this to work properly, as the second method seems like a bit of a hack to me.

In case the entire code snippet helps(of the last thing I tried):

mov word[BALL_X], 0x140
mov word[BALL_Y], 0xF0

main:
    mov ah, 0x00       ;Set video mode
    mov al, 0x12       ;640x480 16 color graphics
    int 0x10           ;Interrupt

    mov ah, 0x0B       ;Set background color
    mov bh, 0x00       ;Set background color
    mov bl, 0x00       ;Black
    int 0x10           ;Interrupt
    
    
    mov ah, 0x0C       ;Write pixel
    mov al, 0x0F       ;White
    mov bh, 0x00       ;Page number
    mov cx, [BALL_X]   ;X
    mov dx, [BALL_Y]   ;Y
    int 0x10           ;Interrupt
    
    jmp exit


exit:
    jmp $


BALL_X equ $
BALL_Y equ $

times 510-($-$$) db 0  ;padding
db 0x55, 0xAA          ;magic bytes to make it bootable
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Chemir
  • 1
  • 1
    The first way with `dw` is correct. `equ` is wrong as it defines a constant without reserving any memory, and you will end up with `BALL_X` and `BALL_Y` both pointing to the same address, so that your second `mov` overwrites the first. So the question is why the `dw` version didn't work. Please post that version of the code ([mcve]); it probably has some other bug. – Nate Eldredge Mar 28 '21 at 16:29
  • 2
    Sections are pretty meaningless in a boot sector where you need a flat chunk of memory laid out in a particular order. One common mistake is to locate your variables before the code, or somewhere else that's in the path of the code, so that they end up getting executed - any chance that's the issue? – Nate Eldredge Mar 28 '21 at 16:31
  • 1
    When you say "it doesn't seem to contain any value" - that doesn't really make sense, memory always contains some value. What is it that you actually observe? – Nate Eldredge Mar 28 '21 at 16:33
  • 2
    Good practise also indicates to set up the segment registers before accessing memory. `xor ax, ax` \ `mov ds, ax` before any memory access achieves this. – ecm Mar 28 '21 at 16:58
  • 2
    Your example is missing the `org 7C00h` line too. – ecm Mar 28 '21 at 16:59
  • 1
    @ecm: The default `org` is `0` if you don't use an org directive, right? So I think it's a duplicate of Michael Petch's nice long answer on [Reading from memory in 8086 real mode while using 'ORG 0x0000'](https://stackoverflow.com/q/34411336) that describes what's going on. (Except for the `equ` attempt!) – Peter Cordes Mar 28 '21 at 17:30
  • @ecm That seems to have fixed it, thank you! – Chemir Mar 28 '21 at 17:35
  • @Peter Cordes: Yes, omitting the `org` is equivalent to setting it to zero. To be fair, you could do that and have it turn out correct if you initialised `ds` to 7C0h. – ecm Mar 28 '21 at 18:23
  • I've seen a few boot sector games that use the screen memory as a place to store variables. – puppydrum64 Dec 22 '22 at 18:07

0 Answers0