Code: Select all
section .text
global start
start:
mov eax, 0xb8000
mov [eax], byte 0x41
mov [eax + 1], byte 0x1f
loop1: jmp loop1
Code: Select all
section .text
global start
start:
mov eax, 0xb8000
mov [eax], byte 0x41
mov [eax + 1], byte 0x1f
loop1: jmp loop1
Code: Select all
[ORG 0x0]
start:
mov ax, 0xb800
mov es, ax
mov ax, 0
mov [es:ax], byte 0x41
mov [es:ax + 1], byte 0x1f
loop1: jmp joop1
bootmagic:
times 510-($-$$) db 0
db 0x55
db 0xaa
Code: Select all
8: error: invalid effective address
9: error: invalid effective address
Code: Select all
mov [es:ax], byte 0x41
mov [es:ax + 1], byte 0x1f
Code: Select all
times 510-$ db 0
I'll tackle this bit@modi wrote:I also haven't really done a lot of programming with segments, so I don't think I fully understand why 0000:7C00 and 07C0:0000 have different effects. Also, what's a far jump?
Sorry, I tested it with di* instead of ax on my system, I just changed it to ax to post as that was what you were using in the original post. If you change ax in these three lines to di it should work fine (or eax etc).@modi wrote:Code: Select all
mov ax, 0 mov [es:ax], byte 0x41 mov [es:ax + 1], byte 0x1f
AJ's answered most of this. The reason I mentioned it is because, even though they are the same address, the segment is different in each. For example, if you make use of a non-relative (i.e. absolute) near jump in your bootloader, you'll end up in a different place if your code segment is 0x0000 or 0x07c0. It would be nice if all bioses loaded your boot loader to the same segment, but unfortunately they don't.@modi wrote:I also haven't really done a lot of programming with segments, so I don't think I fully understand why 0000:7C00 and 07C0:0000 have different effects. Also, what's a far jump?
Code: Select all
[ORG 0x0]
jmp 0x07c0:start
start: ...
Ok, I'll have to check the manuals. I ended up using EAX because I remembered something about a 16 bit segment register and 32 bit offset, so I tried it, but I didn't really know what I was doing. Now I understand better. I'll have to read the manuals in detail, so I know what I'm doing in the future.Combuster wrote:16-bit addressing is very different from 32-bit addressing. The scale-index-base addressing you are used to won't work. Instead you only have a limited set of register combinations. [AX] is not among them.
For a quick fix, use bx, otherwise look at the intel manuals for the complete set of allowed effective addresses. You can also zero out the top of AX and then use [EAX], at the cost of pre-386 compatibility
AJ wrote:A far jump is a jump involving both the segment and offset, as opposed to a jump which just specifies the offset.
JMP 0x10:0x1000 is a far jump
JMP 0x1100 is not.
Thanks, these clear things up quite a bit. For some reason I kept thinking that 0x0000 and 0x07C0 were completely independent parts of memory without realizing they can be used with different offsets to refer to the same location (i.e. I always think of segments as completely independent and separate address spaces, but in reality, on the x86, they aren't always). I didn't see why jumping to 0x7C00:0000 was useful because I was effectively thinking of address 0x7C00:0000 as absolute address 0x00000000 (which is where for some reason I was thinking the bios loaded the boot sector to) and 0x0000:7C00 as absolute address 0x00007C00 (which I was thinking of as a completely unrelated, uninitialized address with unknowable and meaningless contents). Now I finally realize they are the exact same absolute address and that absolute jumps are computed from within the current segment, so 0x0000 and 0x7C00 have different effects.jnc100 wrote:AJ's answered most of this. The reason I mentioned it is because, even though they are the same address, the segment is different in each. For example, if you make use of a non-relative (i.e. absolute) near jump in your bootloader, you'll end up in a different place if your code segment is 0x0000 or 0x07c0. It would be nice if all bioses loaded your boot loader to the same segment, but unfortunately they don't.@modi wrote:I also haven't really done a lot of programming with segments, so I don't think I fully understand why 0000:7C00 and 07C0:0000 have different effects. Also, what's a far jump?
To get around this, one of the things you can do is, at the start of your bootloader, something like:
this enforces cs to be 0x07c0, and all offsets start from 0x0.Code: Select all
[ORG 0x0] jmp 0x07c0:start start: ...
it seems you still dont get itI didn't see why jumping to 0x7C00:0000 was useful because I was effectively thinking of address 0x7C00:0000
Oh, yeah, sorry that was just a typo. I do understand that segment registers refer to 16 byte paragraph boundaries, which is equivalent to shifting an absolute address right one hex digit (to which the inverse operation is shifting left one hex digit, or, equivalently, multiplying by 0x10) because hex is base 16, so 0x10 has a value of 16 (base 10). I was just tired cause it was the early morning and wrote 0x7C00:0000 when I meant 0x07C0:0000. I definitely understand that part now though.JAAman wrote:it seems you still dont get itI didn't see why jumping to 0x7C00:0000 was useful because I was effectively thinking of address 0x7C00:0000
you definately dont want 0x7C00:0000 -- that is uninitiallized memory
what you want is 0X07C0:0000 (which is an alias for 0:7C00)
remember to multiply your segment by 0X10 before adding your offset to find the absolute address
and (unrelated to the first quote):jnc100 wrote:If you're writing a bootsector for hard disks (insetead of floppies), you need the jump anyway, but someone else can go into that.
@modi wrote:I assembled and ran it and got the same output as before. I'm starting to think [the problem] is the computer I'm using to test the sector on. It's an old laptop and might be incompatible or something. I think I need to use an emulator. What's a good one? I'd like to try it on VMware, but my floppy drive is a USB device and VMware Server doesn't recognize it because it keeps trying to read it as an IDE device or something. Does anyone know how to construct a VMware .vmdk disk image?
I don't use VMWare, but it works in bochs and qemu. To create a 1.44MB image I use the following:@modi wrote:I assembled and ran it and got the same output as before. I'm starting to think [the problem] is the computer I'm using to test the sector on. It's an old laptop and might be incompatible or something. I think I need to use an emulator. What's a good one? I'd like to try it on VMware, but my floppy drive is a USB device and VMware Server doesn't recognize it because it keeps trying to read it as an IDE device or something. Does anyone know how to construct a VMware .vmdk disk image?
Code: Select all
[ORG 0x0]
jmp 0x07c0:start
start:
mov ax, 0xb800
mov es, ax
mov di, 0x0
mov [es:di], byte 0x41
mov [es:di + 1], byte 0x1f
loop1: jmp loop1
bootmagic:
times 510-($-$$) db 0
db 0x55
db 0xaa
times 1474560-($-$$) db 0
Code: Select all
;boot sector
[ORG 0x0]
start:
mov ax, 0xb800
mov es, ax
mov eax, 0
clear_screen:
mov [es:eax], byte ' '
mov [es:eax + 1], byte 0x7F
add eax, 2
cmp eax, 8000
jl clear_screen
mov eax, 0
mov [es:eax], byte 'I'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 't'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte ' '
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 'w'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 'o'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 'r'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 'k'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte 's'
mov [es:eax + 1], byte 0x1f
add eax, 2
mov [es:eax], byte '!'
mov [es:eax + 1], byte 0x1f
loop_done: jmp loop_done
bootmagic:
times 510-($-$$) db 0
db 0x55
db 0xaa
times 1474560-($-$$) db 0
You can do:@modi wrote:Code: Select all
clear_screen: mov [es:eax], byte ' ' mov [es:eax + 1], byte 0x7F add eax, 2 cmp eax, 8000 jl clear_screen
Code: Select all
clear_screen: cld
xor di, di
xor ax, ax; or mov ax, 0x7f20 if you like
mov cx, 2000
rep stosw