6

I am trying to print a string in Q Emulator using NASM. My code is as below:

mov bx,HELLO
mov ah, 0x0e
int 0x10
HELLO:
  db 'Hello', 0
jmp $
times 510-($-$$) db 0
dw 0xaa55

However when I compile this code, the output that I get is

UU

Can anyone please tel me why this is so? And how to get the required string as output?

Thanks in advance.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Sanket Gupte
  • 357
  • 1
  • 4
  • 16
  • 2
    You don't show how you assemble this, but one thing that strikes me is that you don't have an ORG directive at the top. Like `ORG 0x7c00` . Possible you used `-f bin` when assembling with _NASM_ and it used a default ORG of 0x0000. Although that won't be your issue. Int 10h/ah=0eh prints one character at a time, and doesn't take a memory address in _BX_ – Michael Petch Oct 20 '16 at 00:29
  • Yes, this is a test program. I am actually trying to understand how to call macros but can't get it to run this code properly. I am using -f bin when assembling with NASM – Sanket Gupte Oct 20 '16 at 00:33
  • 1
    You should also place your data after the `jmp $` . Placing it before the JMP will cause the processor to decode the data in `HELLO` as instructions and could lead to unexpected behaviour. – Michael Petch Oct 20 '16 at 00:36
  • 2
    If you wish to use int 0x10h/0eh to print a string you have to do it character by character. The `print_string` in this tutorial may be of use: http://mikeos.sourceforge.net/write-your-own-os.html – Michael Petch Oct 20 '16 at 00:37
  • I tried that as well Michael but it didn't work – Sanket Gupte Oct 21 '16 at 14:58
  • 2
    What happens if you try a complete example like this one: http://www.capp-sysware.com/misc/stackoverflow/40143596/boot.asm . This sets up a stack, initializes ES and DS appropriately and creates a `_print_string` function that loops through a null terminated string printing each character one by one using INT 10h/AH=0eh. – Michael Petch Oct 21 '16 at 15:40

2 Answers2

4

ALRIGHT SO here is a thingamabob to your question

In order to load the string, you must move it into si (don't really want to go to deep but just do it). Next in order to load a character into the register AL use lodsb. Next, we must print it so use int 10h mov ah, 0Eh. Int 10h handles the video and ah tells BIOS to print whatever we have in al (aka lodsb). Next, we must have an ending loading char so we just don't loop forever. Me personally I use 0x00 however you use 0. 0x00 is much better in my case because not only can u use 0, 0x00 does not print anything so why would u ever need it?

ALRIGHT so we got everything done and going here is the code:

    mov si, message       ;The message location *you can change this*
    call print            ;CALL tells the pc to jump back here when done

    print:
      mov ah, 0Eh         ;Set function

    .run:
      lodsb               ;Get the char
    ; cmp al, 0x00        ;I would use this but ya know u dont so use:
      cmp al, 0           ;0 has a HEX code of 0x48 so its not 0x00
      je .done            ;Jump to done if ending code is found
      int 10h             ;Else print
      jmp .run            ; and jump back to .run

    .done:
      ret                 ;Return

    message           db  'Hello, world', 0 ;IF you use 0x00
    ;message          db  'Hello, world', 0x00

Logan Rios
  • 87
  • 10
  • 3
    `0` (decimal) and `0x00` (hex) are the same number. `'0'` is a way to write `48` or `0x30` in NASM syntax, maybe that's what you were thinking of when you wrote those comments about `0` vs. `0x00`? And yes, `'0'` would be a terrible choice of terminator, but `0` is 100% normal. Notice that it's outside the quoted string so it's just a number. – Peter Cordes Apr 12 '21 at 01:28
  • 3
    Using `lodsb` is *one* way to loop over a string; if you do that then yes you need the pointer in DS:SI (https://www.felixcloutier.com/x86/lods:lodsb:lodsw:lodsd:lodsq) with DS set to match the ORG setting (which the BIOS doesn't always do for you in a bootloader; multiple different possible DS values are possible on different machines so you should set DS yourself in a legacy BIOS bootloader like the question is writing.) – Peter Cordes Apr 12 '21 at 01:32
  • @Logan Rios 0 is only defined as 0x48 (ASCII hexadecimal value) if surrounded with an apostrophe because the assembler will see it as a string rather than a hexadecimal value. – FryingRonald Nov 12 '21 at 14:40
-2

I found this code from here and it worked for me. Use nasm and compile as a bin, then use the .flp file as boot info and boot it. Hopefully, it can work for you too.

  • 1
    Stack Overflow answers should be self-contained, at least partly useful if the link dies. That's not the case here; you could fix that by editing to include some code, and/or explanation of setting `ds` to match the ORG and looping over a string. – Peter Cordes Feb 11 '23 at 21:12