Page 1 of 2
load & execute next sector after bootsector
Posted: Sat Apr 16, 2016 10:56 pm
by bilsch01
The program I have in the boot sector (sector 1) of the first partition is in file boot1.s below. I intend it to be loaded in memory at 7c00:0000, and for it to load the program in kern1.asm (in sector 2 of the first partition) to memory at 7e00:0000 and jump to it. I assembled and linked these two as follows:
as boot1.s -o boot1.o
nasm -f elf kern1.asm -o kern1.o
ld --oformat binary boot1.o kern1.o -o kernel1.bin
I wrote the resulting file (kernel1.bin) to the first 2 sectors of the
first partition with the following command line:
dd if=/sda5/home/bilsch/jinx/kernel1.bin count=2 of=/dev/sda1 count=2
boot1.s should print 'ABCD' if int 0x13 ah=0x42 returns cf=0. I intend it to also set up the 'disk address packet' at 7c00:0x100, and run Int 0x13 ah=0x42 (read sectors), and then execute the code from sector 2 via a far call to 07e0:0000. The code from sector 2 should print '123'. If everything goes as planned the result should be 'ABCD123'. But when I boot the partition it just prints ABCD and stops. The fact that the 'D' prints indicates that int 0x13 was successful. I think the far call does not reach the code of kern1 but I can't figure why. Maybe specifying lba sector 2 is wrong, though the command line should write kernel1.bin to the first two sectors of partition 1.
I have verified that the ELF header of kern1.o is not linked into the resulting kernel1.bin, and that the code of kern1 begins at 0x200 of kernel1.bin as it should.
QUESTION: how to load the program from sector 2 and jump to it?
Thanks. Bill S.
boot1.s is as follows:
<code>
.code16
.section .text
.global _start
_start:
push %cs
pop %ds
push %ds
pop %ss
movw $0x7bff, %sp
movw $0x0e41, %ax #A
int $0x10
movw $0x0e42, %ax #B
int $0x10
movw $0x0e43, %ax #C
int $0x10
movw $0x100, %si #offset of buffer
movw $0x10, (%si) #buffer size
movw $1, 2(%si) #one sector
movw $0x0000, 4(%si) #offset
movw $0x07e0, 6(%si) #segment
movw $64, 8(%si) #llba 2 in quadword
movw $0, 10(%si) # mbr=lba0, this=lba1, read=lba2
movw $0, 12(%si)
movw $0, 14(%si)
movb $0x42, %ah #extended read
movb $0x80, %dl #drive number
int $0x13
jc .Lhang #CF=1=failed
movb $0xe, %ah
movb $0x44, %al #D
int $0x10 #CF=0=success
lcall $0x07e0,$0x0000
.Lhang:
jmp .Lhang
***********************************************************
kern1.asm is as follows:
bits 16
SECTION .text
mov ax, 0x07e0
push ax
pop cs
mov ax, 0x0e31 ;1
int 0x10
mov ax, 0x0e32 ;2
int 0x10
mov ax, 0x0e33 ;3
int 0x10
jmp $ ;jmp here infinite loop
</code>
Re: load & execute next sector after bootsector
Posted: Sun Apr 17, 2016 5:29 am
by Octocontrabass
bilsch01 wrote:I intend it to be loaded in memory at 7c00:0000, and for it to load the program in kern1.asm (in sector 2 of the first partition) to memory at 7e00:0000 and jump to it.
Your code and this description do not agree. Which is correct?
It looks like you don't understand how segment:offset addressing works. Can you tell me what you get when you convert those to linear addresses?
bilsch01 wrote:as boot1.s -o boot1.o
nasm -f elf kern1.asm -o kern1.o
Why are you using two different assemblers?
bilsch01 wrote:dd if=/sda5/home/bilsch/jinx/kernel1.bin count=2 of=/dev/sda1 count=2
Why are you testing your code by overwriting the hard disk on your PC? Are you sure /dev/sda1 starts at LBA 1 and not somewhere else?
bilsch01 wrote:movw $0x7bff, %sp
Your stack is not aligned correctly, and probably also not where you think it is.
bilsch01 wrote:movw $64, 8(%si) #llba 2 in quadword
Does 64 equal 2? Does /dev/sda1 actually start at LBA 63?
bilsch01 wrote:movb $0x80, %dl #drive number
You shouldn't hard-code the drive number.
bilsch01 wrote:pop cs
Which CPUs understand this instruction?
Re: load & execute next sector after bootsector
Posted: Sun Apr 17, 2016 1:29 pm
by onlyonemac
Octocontrabass wrote:bilsch01 wrote:pop cs
Which CPUs understand this instruction?
Does that code even assemble???
EDIT: I see he's got Linux running on his 8086.
Re: load & execute next sector after bootsector
Posted: Sun Apr 17, 2016 5:04 pm
by Schol-R-LEA
@blisch1: Oh, and FYI: you need to use the square-bracketed BBcode tags for the CODE blocks in your messages, not HTML/XML style tags. In order to minimize the risks of malicious script injection, nearly all message boards trap any HTML tags submitted through the editor, and usually escape the angle brackets into the HTML entity forms. They usually have some simplified (and somewhat more secure) markup format to allow the users to add formatting; in PHPBB, which this forum uses, the markup language is
BBcode, which looks like:
Code: Select all
[code]My Code Here
More Code Here
Even More Code Here
[/code]
You should be still able to go back and edit the post, and I recommend doing so. Now, this is the sort of thing almost everyone gets wrong the first time, and formatting is not tremendously important for assembly code, so it's no big deal, really, but please keep this in mind for the future. I also recommend getting familiar with both BBcode and
Markdown, as those are the two most widely used forum markup languages right now.
(yeah, I know, I know, but Markdown is popular for some reason, and it usually works well enough in non-technical fora. Besides, almost every complaint I ever heard about it was regarding the Discourse implementation of Markdown, and DiskHorse is so bad in general that it makes the Bibby Jebus cry - there are several reasons why the nickname 'DiskHorse' is one of the few pejoratives applied to Discourse that I could post here without the mods deleting it, with Jeff Atwood himself being #1 on the list with a bullet. While the project was overly ambitious and tried to do too many new things at once, most of those issues could have been fixed had Jeff not been so stubbornly pigheaded in refusing to listen to users' complaints and bug reports; but it was his high-handed insistence on holding, and abusing, admin privileges on every site using his software on the grounds of 'maintaining a civilized discourse' that really pushed it into unmitigated disaster territory. If @wood had set out to create an object lesson in how not to manage and maintain publicly facing software, well, mission accomplished.)
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 8:32 am
by bilsch01
Thanks for your comments. I made changes as you suggested. I got rid of GAS. File boot1.s is now bootn1.asm, assembled with NASM. I no longer link the sector 1 file with the sector 2 file, I have two binary files: bootn1.bin (in the first sector of the first partition1) and kern1.bin (in the second sector). bootn1.bin prints 'ABC' and if the int 13 call is successful it also prints 'D''. It then should read file kern1.bin from disk and load it at 07e0:0000 and jump to it and execute it. kern1.bin should print '123'. If everything works right the result should be 'ABCD123'. But it prints 'ABCD' and stops. Do you have suggestions for what I should do? The new programs are listed below. The command lines for writing them to disk are:
dd if=/mnt/sda5/home/bilsch/jinx/bootn1.bin count=1 of=/dev/sda1 count=1
dd if=/mnt/sda5/home/bilsch/jinx/kern1.bin count=1 of=/dev/sda1 seek=1 count=1
bootn1.asm is as follows:
Code: Select all
bits 16
section .text
global _start
_start:
push cs
pop ds
push ds
pop ss
mov sp, 0x7c00
mov ax, 0x0e41 ;A
int 0x10
mov ax, 0x0e42 ;B
int 0x10
mov ax, 0x0e43 ;C
int 0x10
mov si, 0x100 ;offset of buffer
mov word [si], 0x10 ;buffer size
mov word [si+2], 1 ;one sector
mov word [si+4], 0x0000 ;offset
mov word [si+6], 0x07e0 ;segment
mov word [si+8], 2 ;lba 2 in quadword
mov word [si+10], 0 ; mbr=lba0, this=lba1, read=lba2
mov word [si+12], 0
mov word [si+14], 0
mov ah, 0x42 ;extended read
; dl is unchanged since start - set by BIOS
int 0x13
jc Lhang ;CF=1=failed
mov ax, 0x0e44 ;D CF=0=success
int 0x10
call 0x07e0:0x0000 ;far call
Lhang:
jmp Lhang
times 510-($-$$) db 0
dw 0xAA55
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
kern1.bin is as folows:
bits 16
org 0x7e00
SECTION .text
; segment regs were set in calling program, int 13 loads this at 07e0:0000
mov ax,0x0e31 ;1
int 0x10
mov ax,0x0e32 ;2
int 0x10
mov ax,0x0e33 ;3
int 0x10
jmp $ ;jmp here infinite loop
times 512 -($-$$) db 0
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 9:00 am
by Schol-R-LEA
Do you mind me asking how you intend to determine if this is working correctly or not? Without some sort of output, it really isn't easy to tell unless you step through it in an emulator's debugger.
This reminds me, one of the many projects I have been putting off is cleaning up
Verbum and getting it to the point where it actually does work with FAT12; I keep meaning to go back to it but I haven't done much with it in about ten years aside from moving it from Subversion to git and putting it on Github. Getting some additional eyes on it would help, too.
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 9:03 am
by Octocontrabass
Did you write the MBR? If not, you shouldn't rely on CS, because it could contain any value.
Have you confirmed that /dev/sda1 starts at LBA 1 and not somewhere else?
These two lines disagree with each other. Do you know why?
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 9:13 am
by iansjack
Your org directive in the second program is incorrect. It should be org 0x0. But the program is so simple that that should make no difference.
You seem to be loading the 3rd sector, not the second one.
Moral; run this under a debugger and look at what is actually loaded.
You talk about the "first partition". Is your drive actually partitioned? (Edit: Yes, it looks like you are dealing with a partitioned disk - or at least think you are - which explains the 2nd/3rd sector business. But in that case the first partition almost certainly doesn't start immediately after the MBR. A disk editor will let you check this.)
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 11:30 pm
by bilsch01
Octocontrabass wrote:
Did you write the MBR? If not, you shouldn't rely on CS, because it could contain any value.
I hadn't thought about it. The MBR code could be written by any of a number of utilities, but 'they' say the code jumps to 7c00 - I assumed that was standard PC rule everybody follows and that CS would be set accordingly. What code is legal for setting CS? Apparently not pop CS. Not mov cs,ax. What is it?
Have you confirmed that /dev/sda1 starts at LBA 1 and not somewhere else?
Now that you mention it, I realize it starts at CHS 0,1,1 = lba 63. I see that is a problem with my code.
These two lines disagree with each other. Do you know why?
I don't understand why. (07e0 times '16')=7e00. 7e00 + 0000 = 7e00. Doesnt org 7e00 mean add 7e00 to all the labels? That's what I need to do, isn't it? Please explain whats wrong.
Re: load & execute next sector after bootsector
Posted: Mon Apr 18, 2016 11:54 pm
by bilsch01
iansjack wrote:Your org directive in the second program is incorrect. It should be org 0x0. But the program is so simple that that should make no difference.
How will it know it is to be running at 7e00? Is that because I said to load it there with int 13, ah=42?
You seem to be loading the 3rd sector, not the second one.
Moral; run this under a debugger and look at what is actually loaded.
I've not had much luck getting gdb to run in qemu. That's all I tried so far.
You talk about the "first partition". Is your drive actually partitioned? (Edit: Yes, it looks like you are dealing with a partitioned disk - or at least think you are - which explains the 2nd/3rd sector business. But in that case the first partition almost certainly doesn't start immediately after the MBR. A disk editor will let you check this.)
Cam you tell me a good one that runs in linux? I tried LDE - I cant get meaningful display with LDE.
Re: load & execute next sector after bootsector
Posted: Tue Apr 19, 2016 5:01 am
by Combuster
bilsch01 wrote:I don't understand why. (07e0 times '16')=7e00. 7e00 + 0000 = 7e00. Doesnt org 7e00 mean add 7e00 to all the labels? That's what I need to do, isn't it? Please explain whats wrong.
So your segment is 07e0 and adds 7e00 to everything, and you have an org that adds 7e00 to all the labels. What is
two times 7e00?
Re: load & execute next sector after bootsector
Posted: Tue Apr 19, 2016 6:57 am
by iansjack
bilsch01 wrote:Cam you tell me a good one that runs in linux?
For pure assembler stuff like this, debugging right from boot, I would use SimNow (
http://developer.amd.com/tools-and-sdks ... simulator/ ) Once you do things properly and write your OS in C you need gdb. It's very easy to get this working with qemu.
Re: load & execute next sector after bootsector
Posted: Tue Apr 19, 2016 7:08 am
by glauxosdever
Hi,
bilsch01 wrote:I don't understand why. (07e0 times '16')=7e00. 7e00 + 0000 = 7e00. Doesnt org 7e00 mean add 7e00 to all the labels? That's what I need to do, isn't it? Please explain whats wrong.
It seems you haven't understood what does the org directive do. It specifies the origin of the offset, not the segment, nor segment:offset. In other words, it specifies at what offset is the first byte of the loaded binary, so the offsets of respective labels are calculated correctly.
So, if you want to load at 0x7E00:
- Either set segments to 0x07E0 and the offset of origin to 0x0000;
- Either set segments to 0x0000 and the offset of origin to 0x7E00 (recommended).
The above list applies both to the far call and the program that is to be loaded.
Regards,
glauxosdever
Re: load & execute next sector after bootsector
Posted: Tue Apr 19, 2016 8:54 am
by onlyonemac
bilsch01 wrote:I don't understand why. (07e0 times '16')=7e00. 7e00 + 0000 = 7e00. Doesnt org 7e00 mean add 7e00 to all the labels? That's what I need to do, isn't it? Please explain whats wrong.
You're correct that "org 7e00" means "add 7e00 to all the labels".
But the labels are relative to your segment register, so "org" should be used to set the offset of the labels
relative to the segment register. In other words, if your code starts at 7e00 and you set the segment register to 07e0 (i.e. a memory address of 7e00), then the instruction pointer is zero when it points to the first instruction in your code, so "org" should be zero; if, say, your code starts at 7e00 and you set the segment register to 07c0 (say you left it as it was from the first sector) then "org" should be 0200, because the code starts at an offset of 0200
from the address pointed to by the segment register.
Re: load & execute next sector after bootsector
Posted: Tue Apr 19, 2016 8:56 am
by onlyonemac
Octocontrabass wrote:bilsch01 wrote:
Have you confirmed that /dev/sda1 starts at LBA 1 and not somewhere else?
Hint: it probably doesn't.