Trouble with int 0x13 ah = 0x42 in VMware

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
flicki
Posts: 2
Joined: Tue Jun 28, 2016 12:33 am

Trouble with int 0x13 ah = 0x42 in VMware

Post by flicki »

I feel really dumb for posting this, but anyway.

I have made a bootloader and it works on QEMU, VirtualBox and Bochs, but not on VMware. I have done some debugging and narrowed it down to int 0x13 ah = 0x42. Now if I change it to ah=2, it works! While this may seem to be the obvious solution, I have already written a stage 2 using the extended bios functions.

Cut it short my question is; has anyone else had trouble with int 0x13 ah = 0x42 in VMware and what was your/their fix.

Some side notes; I have not tested it on real hardware(getting my second computer to work before I do) and if I must do it I can change it to use ah=2.

The code for the boot loader(in case your curious): https://github.com/cxleb/MochaOS/blob/m ... stage1.asm
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by Love4Boobies »

Your DAP is all messed up. You can find its format in the EDD specification, the latest being version 4.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
flicki
Posts: 2
Joined: Tue Jun 28, 2016 12:33 am

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by flicki »

Love4Boobies wrote:Your DAP is all messed up. You can find its format in the EDD specification, the latest being version 4.
I followed the spec, but still same result? i tried another os using extended bios read and it failed too, maybe it is just VMware?
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by Octocontrabass »

You're relying on the (undefined) initial value of DS on line 24.

MOV to SS only disables interrupts long enough for one more instruction to run. Since line 33 is not a MOV to SP, interrupts can occur with an invalid stack. (You can use "mov sp, 0x7c00".)
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by IanSeyler »

For a working example of DAP see here: https://github.com/ReturnInfinity/Pure6 ... fs_mbr.asm
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by Octocontrabass »

flicki wrote:

Code: Select all

dap:
db 16 		; size
db 0 		; unused
dw 16		; sector count
dw 0x0500	; offset
dw 0		; segment
dq 1		; sector read start
IanSeyler wrote:For a working example of DAP see here:

Code: Select all

DAP:	db 0x10
	db 0x00
	dw SECTORS
	dw ADDRESS
	dw SEGMENT
	dq STARTSECTOR
I don't think the problem is the DAP.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by iansjack »

... particularly as the code works on some platforms and not others. I would guess that your point about an assumed value of register DS is the most likely explanation.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by SpyderTL »

I've found that when one VM works and another doesn't, it's because you are making an assumption about the initial state of the machine.

My loader works on VMware, and the only differences that I can see are as follows:

1. You need to clear the direction flag. The BIOS may have left it set when your loader is called.

2. Make sure that your initial JMP is a long jump. You have no idea what CS is set to when your loader is called. (Or, add a second long jump after the first one. I don't think you have room for a long jmp before your MBR.)

3. Try setting your stack pointer to zero instead of 7c00. I doubt this is a problem, but it's worth a shot.

4. Try enabling the A20 address line. Shouldn't matter in your case, but you might as well.

5. If all else fails, try changing your sector count to 1 to see if that works at all.

I'm 99% sure your problem is #2.

Edit: 6. You should also probably clear your FS and GS registers. Just to be safe.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by BenLunt »

I'm actually curious to what the outcome of this is. I also think it is an assumption that VMware emulates different than other emulators.

However, I am pretty sure that it is not that you need to set your CS:IP pair with a long jump. This is a common misunderstanding for boot loaders.

As long as you do not use the CS: override or anything that relies on the CS:IP pair, it doesn't matter what the CS:IP pair evaluates to, and a long jump is not needed at all.

As long as you don't do one of the following:

Code: Select all

  mov  ax,cs
  mov  ds,ax

  call  get_ip
get_ip:
  pop  ax

  mov  cs:[some_data],ax
Along with a few other "so far off" items, it doesn't matter what the CS:IP pair is.

Even

Code: Select all

  ...
this_location:
  mov  ax,offset this_location
doesn't rely on the CS:IP pair. It *does* rely on the ORG (origin) you give the source file, but it does not rely on the CS:IP pair.

For example, the CS:IP pair could be 0020:7A00h or 0123:69D0h for that matter as long as the combined physical address is 0x07C00.

Anyway, I am curious to what you found out. Was it the assumption of the DS value? A bad stack? What?

Thanks,
Ben
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by SpyderTL »

It actually may be the very first line that's the problem...

Code: Select all

mov byte [driveNum], dl
Since, afaik, you have no idea what DS is set to, this will only work (as intended) if DS is set to zero by the BIOS before your loader is called. Your drive letter value is getting stored somewhere, but probably not where you think, and probably not the same place that you pull it from at the end of your loader.

Simply moving this line below your DS/ES reset code will probably fix the problem.

Also, since your DAP structure is inline with your code, I'm thinking that passing the address to int 13h will only work if CS and DS are set to the same value. Which means that you probably want to do a long jmp somewhere near the top of your code.

If this were an exe file, with proper segments, you could probably get away with this, but in this case, you have to keep an eye on your segment registers.

Edit: octocontrabass called the first issue, but I'm sticking by my long jmp call. :)

Another option would be to copy CS to DS. Ironically, BenLunt did exactly this in his example code, when he was trying to prove that this wasn't necessary. :)

And, technically, it has nothing to do with VMWare, and more to do with the BIOS. Making assumptions about the initial state of the machine will always fail on any machine that doesn't match your assumptions.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by Octocontrabass »

SpyderTL wrote:Also, since your DAP structure is inline with your code, I'm thinking that passing the address to int 13h will only work if CS and DS are set to the same value.
The value of CS doesn't matter for that. What matters is that you tell the assembler (with an org statement) how to calculate the offsets in the segment you're using. Since the extended read function uses DS:SI, you need DS to agree with your org statement.
SpyderTL wrote:Edit: octocontrabass called the first issue, but I'm sticking by my long jmp call. :)
You only need a long jump (or some equivalent) if you rely on the value of CS. It's still a good idea, but it's unnecessary in this situation.
SpyderTL wrote:Another option would be to copy CS to DS. Ironically, BenLunt did exactly this in his example code, when he was trying to prove that this wasn't necessary. :)
No irony here, BenLunt is correct. You don't know the value of CS, so copying it to DS means you still don't know the value of DS.
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by mikegonta »

flicki wrote:I feel really dumb for posting this, but anyway.
I have made a bootloader and it works on QEMU, VirtualBox and Bochs, but not on VMware. I have done some debugging and
narrowed it down to int 0x13 ah = 0x42. Now if I change it to ah=2, it works! While this may seem to be the obvious solution,
I have already written a stage 2 using the extended bios functions.
Cut it short my question is; has anyone else had trouble with int 0x13 ah = 0x42 in VMware and what was your/their fix.
It's no use guessing (as the other respondents, even if they are right, are doing). Here is a simple (probably too simple for most)
boot program (FASM/NASM) which prints the relevant register values on startup.

Code: Select all

org 0x7C00
start:
  push sp
  push 0xBEEF
  push ss
  push es
  push ds
  push cs
  push 0xFEED
  pushf
  xor ax, ax
  mov ds, ax
  mov es, ax
  mov cx, 7
  mov si, strings
  call print
  pop ax
  call print_binary
  call print_return
.1:
  call print
  pop ax
  call print_hex
  call print_return
  loop .1
  
  jmp $
  
print:
  cld
.1:
  mov ah, 0x0E
  xor bh, bh
  lodsb
  test al, al
  je .2
  int 0x10
  jmp .1
.2:
  ret
  
print_hex:
  push cx
  mov dx, ax
  mov ah, 0Eh
  xor bx, bx
  mov cx, 4
.1:
  rol dx, 4
  mov al, dl
  and al, 0Fh
  add al, '0'
  cmp al, '9'
  jbe .2
  add al, 'A'-('9'+1)
.2:
  int 10h
  loop .1
  pop cx
  ret

print_binary:
  push cx
  mov dx, ax
  mov ah, 0Eh
  xor bx, bx
  mov cx, 16
.1:
  rol dx, 1
  mov al, dl
  and al, 1
  add al, '0'
  int 10h
  loop .1
  pop cx
  ret

print_return:
  mov ah, 0Eh
  xor bx, bx
  mov al, 0x0D
  int 10h
  mov al, 0x0A
  int 10h
  ret
  
strings:
  db "FLAGS = ", 0
  db "FEED = ", 0
  db "CS = 0x", 0
  db "DS = 0x", 0
  db "ES = 0x", 0
  db "SS = 0x", 0
  db "BEEF = ", 0
  db "SP = 0x", 0

  times 510 - ($-$$) db 0
  dw 0xAA55
qemu.png
VMware.png
The main difference is the DS value, which VMware has left at the BDA segment value and not zero which it needs to be set to for
an org 0x7c00.
So, it seems that assuming a DS value was the issue here. Of course neither int 0x13 should have worked with an incorrect DL value,
so it's more than likely not the only issue here.
Remember, when you ASSUME you make an ASS out of yoU and other forum MEmbers.
Last edited by mikegonta on Mon Feb 06, 2017 9:07 am, edited 1 time in total.
Mike Gonta
look and see - many look but few see

https://mikegonta.com
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Trouble with int 0x13 ah = 0x42 in VMware

Post by SpyderTL »

I was thinking that you would also run into problems with near jmp/call instructions if the address was absolute, but it turns out that no such instruction exists on the x86.

There are a few indirect absolute jump functions... those probably wouldn't work. :)

EDIT: Nevermind. Indirect jumps are basically pointers with a CS value and an offset. You guys are right... CS doesn't matter at all. But I'm still not removing my far jmp... :)
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Post Reply