<p>This is a low-level systems question.</p>

<p>I need to mix 32 bit and 16 bit code because I'm trying to return to real-mode from protected mode. As a bit of background information, my code is doing this just after GRUB boots so I don't have any pesky operating system to tell me what I can and can't do.</p>

<p>Anyway, I use [BITS 32] and [BITS 16] with my assembly to tell nasm which types of operations it should use, but when I test my code use bochs it looks like the for some operations bochs isn't executing the code that I wrote. It looks like the assembler is sticking in extras <code>0x66</code> and <code>0x67</code>'s which confuses bochs.</p>

<p>So, how do I get nasm to successfully assemble code where I mix 32 bit and 16 bit code in the same file? Is there some kind of trick?
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­</p>

[{'answer_id': 18359, 'author': 'Neall', 'author_id': 619, 'author_profile': 'https://Stackoverflow.com/users/619', 'pm_score': 0, 'selected': False, 'text': "<p>You weren't kidding about this being low-level!</p>\n\n<p>Have you checked the generated opcodes / operands to make sure that nasm is honoring your BITS directives correctly? Also check to make sure the jump targets are correct - maybe nasm is using the wrong offsets.</p>\n\n<p>If it's not a bug in nasm, maybe there is a bug in bochs. I can't imagine that people switch back to 16-bit mode from 32-bit mode very often anymore.</p>\n"}, {'answer_id': 18364, 'author': 'Curt Hagenlocher', 'author_id': 533, 'author_profile': 'https://Stackoverflow.com/users/533', 'pm_score': 2, 'selected': False, 'text': '<p>The 0x66 and 0x67 are opcodes that are used to indicate that the following opcode should be interpreted as a non-default bitness.  More specifically, (and according to <a href="http://nasm.sourceforge.net/doc/nasmdoc5.html" rel="nofollow noreferrer">this link</a>),</p>\n\n<p>"When NASM is in BITS 16 mode, instructions which use 32-bit data are prefixed with an 0x66 byte, and those referring to 32-bit addresses have an 0x67 prefix. In BITS 32 mode, the reverse is true: 32-bit instructions require no prefixes, whereas instructions using 16-bit data need an 0x66 and those working on 16-bit addresses need an 0x67."</p>\n\n<p>This suggests that it\'s bochs that at fault.</p>\n'}, {'answer_id': 18397, 'author': 'Nathan Fellman', 'author_id': 1084, 'author_profile': 'https://Stackoverflow.com/users/1084', 'pm_score': 0, 'selected': False, 'text': "<p>If you're in real mode your default size is implicitly 16 bits, so you should use BITS 16 mode.  This way if you need a 32-bit operand size you add the 0x66 prefix, and for a 32-bit address size you add the 0x67 prefix.</p>\n\n<p>Look at the Intel IA-32 Software Developer's Guide, Volume 3, Chapter 16 (MIXING 16-BIT AND 32-BIT CODE; the chapter number might change according to the edition of the book):</p>\n\n<blockquote>\n  <p>Real-address mode, virtual-8086 mode, and SMM are native 16-bit modes.</p>\n</blockquote>\n\n<p>The BITS 32 directive will only confuse the assembler if you use it outside of Protected Mode or Long Mode.</p>\n"}, {'answer_id': 20133, 'author': 'Terry', 'author_id': 2171, 'author_profile': 'https://Stackoverflow.com/users/2171', 'pm_score': 3, 'selected': False, 'text': "<p>The problem turned out to be that I wasn't setting up my descriptor tables correctly. I had one bit flipped wrong so instead of going to 16-bit mode I was going to 32-bit mode (with segments that happened to have a limit of one meg). </p>\n\n<p>Thanks for the suggestions!</p>\n\n<p>Terry</p>\n"}]
['https://Stackoverflow.com/questions/18324', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/-1/']