1

Does somebody know what's wrong with the following code?

I cannot make it to work the way I want it. I just want to print a single character of a variable (the letter 'h').

To do that I just copy contents using indirect addressing via the square brackets

[]

; Set BIOS print screen settings
mov ah, 0x0e ; Teletype
mov bh, 0  ; Page number
mov bl, 4  ; Red on black (00000100 - High 0000 is black, low 0100 is red)
mov cx, 1  ; Writes one character

; Printing to screen
mov al, [msg] ; Copy the contents of 'H' into 'al'; IT SEEMS THIS IS NOT WORKING!!!
jmp print_char ; Jump to executable code and do not let CPU step on DATA SECTION

; [BEG DATA SECTION]
  msg: db 'HELLO', 0
; [END DATA SECTION]

print_char:
int 0x10 ; Call BIOS routine to print the char located at 'al'

infinite_loop:
jmp $
times 510 -($-$$) db 0 ; Pad with 0 until byte 510
dw 0xAA55 ; MBR Boot code signature

What I get is a screen that prints "nothing" (Probably an ASCII non-printable character: enter image description here

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Leonardo
  • 63
  • 8
  • Can you a description of the result you get with your original code to your question? – Sami Hult Nov 05 '17 at 12:13
  • Sure. I added a screenshot of the results. I am using QEMU. It is working fine when I just use an immediate value. – Leonardo Nov 05 '17 at 12:19
  • Also helpful would be adding the commands you use to compile this piece, description of the platform and processor, and since this is a very short program, maybe a hex dump of your compiled file. I can see nothing illegal in your code, and start to think this is a question of dereferencing not working because of either wrong state of registers, or word alignment of your code. – Sami Hult Nov 05 '17 at 13:46
  • 1
    If this is your complete code you are lacking an `org 0x7c00` at the top so that absolute offsets will start from 0x7c00 and not 0 within your code. Without it is assumes offsets will be from a base of 0 when loaded in memory. As well you should set _DS_ to 0 before the rest of your code with `xor ax, ax` `mov ds, ax`. I have some bootloader tip in the [Stackoverflow Answer](https://stackoverflow.com/a/32705076/3857942) – Michael Petch Nov 06 '17 at 03:02
  • 1
    @MichaelPetch Thanks lot for you answer!!! Indeed. The problem was that it was necessary to execute `org 0x7c00` at the top of the program to work. I will update my question for future reference and also will ook into your bootloader tips. Thanks both of you for your time. – Leonardo Nov 07 '17 at 21:27
  • You should take your edit and create an answer so we can close the question off. It is okay to answer your own question and then accept your own answer. – Michael Petch Nov 07 '17 at 21:36
  • Done. Also what's the effect of DS particularly in the code above if set to 0? It should not affect anything as long as I do not use segments for addressing. Shouldn't it? – Leonardo Nov 07 '17 at 21:51
  • In real mode you are always using segments (most of the time they are implicit not explicit). When accessing a data value in memory in most cases it defaults to _DS_ register for the segment. For instance `mov al, [msg]` is actually the same as `mov al, [ds:msg]`. The segment and offset combine to form a physical address. The physical address is the (segment*16)+offset. A reasonable tutorial primer on real mode segment offset addressing can be found here: http://thestarman.pcministry.com/asm/debug/Segments.html – Michael Petch Nov 07 '17 at 23:42
  • Worth noting that you can directly write to memory address 0xb8000 to modify the screen buffer directly –  Apr 01 '20 at 11:20

1 Answers1

5

The problem was that it was lacking the following instruction at the top:

org 0x7c00

More info regarding this in the answer of @Michael Petch.

Leonardo
  • 63
  • 8