I am trying to draw to screen in Real Mode, so I am trying to access 0xB8000 using segmentation
My assembly code is this
[BITS 16]
org 0x7c00
begin:
mov ah, 0x01 ; disable cursor
mov ch, 0x3f
int 0x10
mov ch, 0x0000
mov cs, 0xb800
mov ah, 0x0000
mov [cs:ah], ch ; invalid effective address
end:
jmp end
times 510 - ($-$$) db 0
dw 0xaa55
How would I address 0xB8000 using segmentation properly?
Remember that cs
is the code segment register. You can't mov
into it. And even if you could you wouldn't like the results; since cs:ip
is used to determine where to fetch instructions, you would find your CPU executing the contents of video memory. So you should use either ds
or es
instead.
Next, you can't load a segment register with an immediate; you can only load it from another register or from memory.
Finally, you can't use an 8-bit register like ah
as the offset part of an address: offsets are 16 bits. In fact, the only registers that can be used in an effective address for 16-bit 8086 are bx, si, di, bp
. See differences between general purpose registers in 8086. (bp
addressing uses the ss
segment instead of ds
unless overwritten, so probably shouldn't be your first choice here.)
So a few options you could use instead:
mov ax, 0xb800
mov ds, ax
mov bx, 0x0000 ; but xor bx, bx is more efficient
mov [bx], ch
mov ax, 0xb800
mov es, ax
mov bx, 0x0000
mov [es:bx], ch
mov ax, 0xb800
mov es, ax
mov [es:0x0000], ch
As a general principle, when writing in assembly, you can't just guess as to which instructions take which combinations of operands; you have to look it up. You can only use those forms which the architecture actually implements, and sometimes their choices don't follow what you might logically assume. There are patterns which you may begin to recognize over time, but as a beginner, plan on referring to the instruction reference for every line you write.