Hi all, I am trying a bootcode for floppy and use the following code to boot from the 1st HDD. But it always failed. If using int 19h it can show boot options correctly. Could you please show what is wrong, thanks. :red
assume cs:code
code segment
start:
;use int 13h
mov ax,0
mov es,ax
push es
mov bx,7c00h
push bx
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov bp,sp
jmp dword ptr ss:[bp]
;use int 19h
;int 19h
code ends
end start
A long time ago I messed around with this. First you have to consider your BIOS as some of the BIOS source code is hardwired in electronics and cann't be changed, some are not. Second, booting from a floppy and then going to a harddrive is a slow(er) process, you should boot directly off your harddrive first, then your floppy. CMOS controls some of this. Lastly, I think your interupts might be wrong, just doesn't look right, but its been a couple of decades since I last review the code. I recommend you get MS-DOS developers gudie book writen in asm lang, it has what you are looking for and includes all the correct interupts, etc.
Steve
it looks to me as though the disk read overwrites itself, so the jmp far ss:[bp] gets wiped out
0000:7E00 might be a better place to use as a read buffer
I have just found out the reason: yes, the disk read overwrites the stack segment which was set by floppy loader. Thanks a lot. :toothy
As solution I have put the stack segment after address 7c00h+512.
And another question:
If setting up BIOS to boot from floppy disk, what is the default SS and SP if no changes by loader?
lol - i don't think there is a defined "standard" location
most bootloaders i have seen set the stack segment:pointer to 0000:7C00h
that way, the stack is just below the boot sector in memory (remember - it grows downward)
in days of old, PC's were available with as little as 256 k ram (or even 64 k, i suppose, although i have never seen less than 256 k)
so, until some code is executed to know how much memory is available, you are supposed to keep things small
nowdays, of course, everyone has oodles of ram, by comparison
keep in mind that 0000:0000 to 0000:03FF is the interrupt vector table
and the BIOS data area is at 0000:0400 (i forget how big it is - not very)
in the BIOS data area is a word that tells how many pages of ram there are
also, the kb buffer, serial/parallel ports, etc
Hi Dedndave, as a beginner I am appreciated for ur kindly help :thumbu
It should be right for dos programs also point the top of stack to the start of code.
1. Problem - manual stack init is req
2. Problem - last indirect jump is to the "moon".
If you use indirect jmp you must specify address in regs.
If you are booting from a floppy and want to boot from a hard drive, the first thing your floppy code needs to do
is relocate itself, because the hdd mbr will expect to be loaded at 0:7c00 which is where your code is. Before you jump to the new
code, you need to at least make DL=80 (the BIOS lets the boot code know the drive number it came from). See if you can find
an example of mbr code, since it's almost the same thing (boot, relocate, load another boot sector, jump to it).
From what I've seen with BIOSes it is usually segment registers = 0 and sp=0. My own boot code starts with
cli
sub ax,ax
mov ds,ax
mov ss,ax
mov sp,7c00h
sti
MASM isn't the assembler to use for this, try FASM (my favourite) or NASM.
QuoteMASM isn't the assembler to use for this...
why do you say that ? - i have written several boot sectors, as well as ROM-able code using MASM
Quote from: dedndave on November 13, 2009, 01:36:46 PM
why do you say that ? - i have written several boot sectors, as well as ROM-able code using MASM
Mainly the licensing terms - "Thou shalt not make code for non-Microsoft Operating Systems".
Anyway, using "org 7c00h" seems to freak masm out a little...
So does switching from 16-bit real mode to 32-bit protected mode...
give me fasm anyday
format binary as "flp"
ORG 7c00h
boot: cli
cld
sub ax,ax
mov ds,ax
mov es,ax
mov ss,ax
mov sp,boot
sti
mov ax,211h
mov bx,7e00h
mov cx,2
sub dx,dx
int 13h
jmp go
rb 510-($-boot)
dw 0aa55h
pmgdt dw 23,pmgdt,0,0
dw 0ffffh,0,9a00h,0cfh
dw 0ffffh,0,9200h,0cfh
go: mov ax,3
int 10h
mov dx,3f2h
sub al,al
out dx,al
@@: in al,64h
test al,2
jnz @b
mov al,0d1h
out 64h,al
@@: in al,64h
test al,2
jnz @b
mov al,0dfh
out 60h,al
cli
lgdt fword [pmgdt]
mov eax,cr0
or al,1
mov cr0,eax
jmp 8:go32
use32
go32: mov ax,16
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,00190000h
@@: inc dword[0b8000h]
jmp @b
rb (80*18*2*512)-1-($-boot)
db 0
One floppy coming up...
oh - lol - well, i never org'ed to 7c00h, as i remember
i think i org'ed it at 0, knowing it was 7c00h (it is 0 in the boot sector)
to make the assembler labels jive with the real world, you can do something like
xor ax,ax
push ax
mov ax,far_label+7c00h
push ax
retf
far_label:
i forget exactly how i did it - lol - i am getting old, ya know
Yes, I remember about using 'OFFSET mylabel+7c00h' and it was a right PITA. The hard part is getting masm to 'seamlessly' stitch together code
from the 'real' segment (use16) to the 'pmode' segment (use32).
ORG 7c00h presented a problem for exe2bin, but no problem for ML 6+ in combination with a linker that supports /TINY.
real16seg segment
org 7c00h
boot: jmp go
go: jmp go
real16seg ends
end
Using link16 I get two problems
1. with the /t switch won't make it (even though it warns me that it's a .com file)
2. without the switch it makes a 32k (7c00+4) .exe file
And try doing the following in one 'segment' in masm
use16
mov eax,cr0
or al,1
mov cr0,eax
jmp 8:go32
use32
go32: mov ax,16
mov ds,ax
Would I replace 'use16' with '.386r' and 'use32' with '.386p'? I don't know.
That's why I recommend fasm for this kind of stuff. Once you get used to the difference (offset/addr are implied, memory is in []) it's a breeze.
This modified code assembled and linked with /TINY produces a 7-byte COM file:
real16seg segment
org 7c00h
entry:
mov ax, offset entry
boot: jmp go
go: jmp go
real16seg ends
end entry
I added code to demonstrate that the ORG 7c00h is working as intended:
0B10:0000 B8007C MOV AX,7C00
0B10:0003 EB00 JMP 0005
0B10:0005 EBFE JMP 0005
Quote from: dedndave on November 11, 2009, 11:28:21 AM
so, until some code is executed to know how much memory is available, you are supposed to keep things small
nowdays, of course, everyone has oodles of ram, by comparison
keep in mind that 0000:0000 to 0000:03FF is the interrupt vector table
and the BIOS data area is at 0000:0400 (i forget how big it is - not very)
About 256 bytes. "The Undocumented PC" also has one
more byte at 0000:0500 as a print screen status byte. There
can be an extended BIOS data area elsewhere in memory,
usually right before the video memory.
Quotein the BIOS data area is a word that tells how many pages of ram there are
also, the kb buffer, serial/parallel ports, etc
It is a word at 40:13 that shows the memory in 1024 byte
blocks/pages. for 640 k it is 280H. Good old unaligned data.
Regards,
Steve N.