x86 Jcc vs address size?

Emulation of old PCs, PC hardware, or PC peripherals.

x86 Jcc vs address size?

Postby superfury » 2019-2-06 @ 21:01

I know that during JCXZ/JECXZ, the address size selects between the ECX and CX registers.

But what happens with the address size on Jcc instructions? I'd assume nothing on rel8. But what happens with the 0F Jcc instructions? Does it affect the immediate size(imm16 vs imm32)? Or does it do nothing?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby peterferrie » 2019-2-08 @ 20:28

Operand size (0x66) will switch between ECX and CX, and 32-bit or 16-bit immediate for 0F Jcc branches). It does nothing for rel8 Jcc.
Address size (0x67) will switch between EIP and IP for the destination address if taken, including for rel8 Jcc.
peterferrie
Oldbie
 
Posts: 638
Joined: 2008-5-08 @ 21:54

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-08 @ 20:39

So, according to the documentation, operand size (0x66) has effect on the opcodes themselves(e.g. 0F80 being 0x0F80XXXX vs 0x0F80XXXXXXXX), so just changing the immediate operand size.

And with those 0F Jcc (0F80-0F8F) switch between EIP and IP depending on the effective address size(determined by the D-bit in CS combined with the 0x67 prefix being present or not)?

So, in 32-bit programs(D-bit set), with 32-bit operand size not being overridden:
0F8012345678 with a 67h prefix will jump to EIP+12345678, masking the EIP result to 16-bits. But the masking to 16-bits won't happen when the 67h prefix isn't used?
And if you don't specify the 67h prefix, it won't mask to 16-bits?

What happens with D-bit set, opcode 660F801234 being executed. So 1234 is added to EIP. Is EIP masked to 16-bits after that or not?

Oddly enough, the 80386 documentation says that the instructions are only depending on the operand size. It says nothing about any address size? So will a 16-bit immediate 0F80(16-bit operand size, but 32-bit address size due to D-bit being set in the CS descriptor) truncate EIP, after adding the immediate to EIP, to 16-bits? Or will the resulting EIP not be truncated in that case?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby Stenzek » 2019-2-09 @ 05:38

Pentium manual says the relative jumps are EIP <= EIP + rel8/rel16/rel32, masked with FFFFh if operand size is 16-bit.

Indirect jumps are EIP <= r/m16 or 32 (so zero-extended?), then masked with FFFFh if operand-size is 16-bit. As the address referred to by the pointer will be the same size, AFAICT the mask here is redundant.

FWIW, using the address size instead of operand size results in OS/2 crashing on boot in my emulator.
Stenzek
Newbie
 
Posts: 58
Joined: 2017-12-08 @ 08:30

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-09 @ 19:37

Good point. I will have to try OS/2 2.0 again. Tried it a long time ago, before many of the 80386 bugfixes. Maybe it'll install and/or run somewhat now, if at least with the 80286 bugfixes. Perhaps 80386 will run, but it might crash with the remaining bugs I can't seem to find(same as Linux crashing on such a thing)?

Edit: The installation disk boots, but I oddly enough see the CPU speed percentage that's enabled in the settings jump from ~28% to 0% at periodic intervals. Perhaps it's doing some weird kind of test?

Edit: Having inserted disk 1 and pressed the enter key, I get a black screen after the blue screen with information, floppy drive activity and a cursor at the bottom left corner of the screen?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby peterferrie » 2019-2-10 @ 00:46

superfury wrote:So, according to the documentation, operand size (0x66) has effect on the opcodes themselves(e.g. 0F80 being 0x0F80XXXX vs 0x0F80XXXXXXXX), so just changing the immediate operand size.


Yes.

superfury wrote:And with those 0F Jcc (0F80-0F8F) switch between EIP and IP depending on the effective address size(determined by the D-bit in CS combined with the 0x67 prefix being present or not)?


Yes, and 70-7F are affected similarly. In 32-bit code, the 0x67 prefix present causes IP to be used as the target address.
In 16-bit, EIP will be used which can allow branching beyond 0xFFFF in unreal mode (otherwise it will crash).

superfury wrote:0F8012345678 with a 67h prefix will jump to EIP+12345678, masking the EIP result to 16-bits. But the masking to 16-bits won't happen when the 67h prefix isn't used?
And if you don't specify the 67h prefix, it won't mask to 16-bits?


That's correct.

superfury wrote:What happens with D-bit set, opcode 660F801234 being executed. So 1234 is added to EIP. Is EIP masked to 16-bits after that or not?


No. Only if 0x67 is present.

superfury wrote:Oddly enough, the 80386 documentation says that the instructions are only depending on the operand size. It says nothing about any address size? So will a 16-bit immediate 0F80(16-bit operand size, but 32-bit address size due to D-bit being set in the CS descriptor) truncate EIP, after adding the immediate to EIP, to 16-bits? Or will the resulting EIP not be truncated in that case?


No truncation in that case, just a smaller style of branching within a 32-bit space.
peterferrie
Oldbie
 
Posts: 638
Joined: 2008-5-08 @ 21:54

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-10 @ 01:20

So, with the 0F80-0F8F and 70-7F opcodes the Address size determines to use (E)IP and truncate it, while the operand size determines the immediate size(imm16 vs imm32 when used)?

What about the other jmp/call instructions that have an immediate offset? Do they use the address size as well for truncation of (E)IP after adding the immediate, just like the 0F80-0F8F and 70-7F instructions?

So opcodes E8, E9, EB? Do they behave like that depending on the Address size as well?

Oddly enough, the 80386 documentation states the opposite: https://css.csail.mit.edu/6.858/2010/re ... 86/Jcc.htm
Code: Select all
IF condition
THEN
   EIP := EIP + SignExtend(rel8/16/32);
   IF OperandSize = 16
   THEN EIP := EIP AND 0000FFFFH;
   FI;
FI;


So 'OperandSize = 16' can mean either 'OperandSize = 16' for most opcodes, but 'AddressSize = 16' for the Jcc opcodes?

So, looking at those instructions, it's actual undocumented behaviour the CPU uses the Address Size attribute(seeing as it's based on CS.D and prefix 0x67(Address size override)) for wrapping EIP to 16-bits, while the documentation says the EIP wrapping(it using IP with compatible effect) is based on the Operand size being 16-bits?

Edit: Bochs source code also seems to imply that the Address size is unused with those instructions: https://sourceforge.net/p/bochs/code/HE ... _xfer16.cc ?
Look at row 38, where it writes a 16-bit IP to EIP(truncating it). Said function is called at line 294 and onwards. So that means the Operand size(which this module implies) affects the resulting EIP directly and no address size attribute is used in these instructions?

Edit: Opcode EB might not have said problem, because it's always using a imm8 immediate value. But E8 and E9 do seem to have this potential problem? Do they truncate EIP when the operand size is 16-bits? Or do they not truncate when the address size is 32-bits?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby Stenzek » 2019-2-10 @ 03:15

I was using OS/2 Warp 3 as a test case, not 2.0. Makes a good test case for protected mode stuff, as it seems to heavily use mixed 16/32-bit code, call gates, etc.

The Am486 manual agrees with the Intel manuals, in which EIP <= EIP + SignExtend(operand) AND FFFFh, if the *operand-size* is 16-bit. It seems like this might be worth testing on real hardware, particularly whether EIP is masked *before* the addition for an effective 16-bit address size. The manuals don't make any mention of this.
Stenzek
Newbie
 
Posts: 58
Joined: 2017-12-08 @ 08:30

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-12 @ 13:42

Any knowledge on the JMP/CALL opcodes E8(CALL imm16), E9(JMP rel16) and EB(JMP imm8)? How does the address size prefix affect those? Do they have the same behaviour as the conditional Jcc opcodes? So do they also use the address size prefix combined with CS.D for determining IP vs EIP and wrapping?

So what effect does 66E8XXXX, 66E9XXXX and 66EBXX have on 32-bit software(CS.D set) with EIP>=0x10000?
And the same with 67 instead of 66 prefix?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby Stenzek » 2019-2-12 @ 14:09

As far as I understand, the "effective operand size" controls how the instruction behaves, so CS.D=0, no prefix = 16-bit, CS.D=0, 66 prefix = 32-bit, CS.D=1, no prefix = 32-bit, CS.D=0, 66 prefix = 16-bit.

For E8/E9, the effective operand size controls the size of the immediate, which is sign-extended and masked if 16-bit. It also controls whether a word or dword is pushed for calls. This is what is in the Intel manuals, and how I have it implemented in my emulator.

The effective address size will change how the modrm bits are interpreted for the effective address in indirect branches. For direct branches (immediate or relative), shouldn't have any effect as far as I can tell.
Stenzek
Newbie
 
Posts: 58
Joined: 2017-12-08 @ 08:30

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-12 @ 14:25

So the Jcc conditional jumps are an exception to the rule, since they use 16-bit EIP masking(AND with 0xFFFF) and masking only when the address size is 16-bits, instead of the operand size(that is what peterferrie seems to imply, as I understand what he's saying)? Also, that behaviour is undocumented behaviour(if peterferrie is right about that)? All other opcodes just behave as documented, masking to 16-bits depending on the operand size only?
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Jcc vs address size?

Postby Stenzek » 2019-2-12 @ 15:03

Can't say for sure what the hardware does, I implemented it as stated in the documents and programs seem to work :) Only way to know for sure is to test it on hardware.
Stenzek
Newbie
 
Posts: 58
Joined: 2017-12-08 @ 08:30

Re: x86 Jcc vs address size?

Postby peterferrie » 2019-2-13 @ 20:48

Gosh. Indeed I have it entirely backwards.
0x66 is the override that affects all transfers of control: 9A/E0/E1/E2/E3/E8/E9/EA/EB/7x/0F 8x.
There are no exceptions, except that it's 0x66 and not 0x67. That was my mistake.

400000: 66 EB 00 will jump to 0x0003.
peterferrie
Oldbie
 
Posts: 638
Joined: 2008-5-08 @ 21:54

Re: x86 Jcc vs address size?

Postby superfury » 2019-2-14 @ 17:41

Just tried OS/2 warp 3 (Blue Spine CD), extracted the DISK0 to DISK3 .DSK images from the DISKIMGS\OS2\35 folder, mounted DISK0.DSK into UniPCemu(afaik there aren't many emulators for the PC that support said format) as a read-only disk, then reversed the BIOS ROM from the Plop BIOS(for booting the CD-ROM, which isn't actually bootable as I've found out), pressed A in the XT-IDE BIOS to boot the floppy disk, after which it displays four white block characters(the filled block, with all pixels set to foreground color, character code 0xDB), followed by a space and the text "OS/2".

I see it throwing a #UD for opcode 0FA*(The 80486-only CMPXCHG) after which I see it faulting a #UD on opcode FFFFh? So something clearly went wrong there?

The last floppy read was from location 0xD6800.

I see it's still in Real mode, so it hasn't entered protected mode yet, as far as I can see.

Edit: Now making a log file with everything running until the FFFFh opcode...
superfury
l33t
 
Posts: 3230
Joined: 2014-3-08 @ 11:25
Location: Netherlands


Return to PC Emulation

Who is online

Users browsing this forum: No registered users and 2 guests