Это дикое предположение, которое на самом деле может быть неверным.Он основан на том факте, что в 32-битном коде относительные кодированные вами команды JMP и CALL имеют размер 5 байтов, а в 16-битном коде - 3 байта.5 байтов - 3 байта = 2 байта.Учитывая, что относительные цели JMP и CALL основаны на расстоянии от начала следующей инструкции, он может подсказать, что могло пойти не так.
Если я возьму этот код:
bits 32
org 0x1000
cli
xor eax,eax
mov eax,0x1f1a
mov esp,eax
sti
jmp 0x1010
push 0x16b4
call 0x14ca
add esp,0x4
jmp 0x101d
И соберите его с:
nasm -f bin stage2.asm -o stage2.bin
И просмотрите 32-битное декодирование с:
ndisasm -b32 -o 0x1000 stage2.bin
Я получу:
00001000 FA cli
00001001 31C0 xor eax,eax
00001003 B81A1F0000 mov eax,0x1f1a
00001008 89C4 mov esp,eax
0000100A FB sti
0000100B E900000000 jmp dword 0x1010
00001010 68B4160000 push dword 0x16b4
00001015 E8B0040000 call dword 0x14ca
0000101A 83C404 add esp,byte +0x4
0000101D E9FBFFFFFF jmp dword 0x101d
Это выглядит правильно.Однако, если я декодирую тот же код, что и 16-битный, с помощью:
ndisasm -b16 -o 0x1000 stage2.bin
я получаю:
00001000 FA cli
00001001 31C0 xor ax,ax
00001003 B81A1F mov ax,0x1f1a
00001006 0000 add [bx+si],al
00001008 89C4 mov sp,ax
0000100A FB sti
0000100B E90000 jmp word 0x100e
0000100E 0000 add [bx+si],al
00001010 68B416 push word 0x16b4
00001013 0000 add [bx+si],al
00001015 E8B004 call word 0x14c8
00001018 0000 add [bx+si],al
0000101A 83C404 add sp,byte +0x4
0000101D E9FBFF jmp word 0x101b
00001020 FF db 0xff
00001021 FF db 0xff
Декодирование инструкций неверно, однако JMP и CALLsприсутствуют и идут в неправильные места памяти.Это ужасно похоже на наблюдения, которые вы видите.
Не видя ваш код, я надеюсь, что к тому моменту, когда вы начнете выполнять этап 2 с 0x1000, вы перейдете в 32-битный защищенный режим.Если нет, то я подозреваю, что это корень ваших проблем.Я считаю, что 32-битные закодированные инструкции выполняются в 16-битном реальном режиме.
Обновление
Из комментариев ОП предлагает, что они вошли в 32-битный защищенный режим как часть процессаввода нереального режима.Они верили, что нереальный режим все равно будет декодировать инструкции как 32-битный код, и, следовательно, проблема.
Вы переходите в нереальный режим, входя в 32-битный защищенный режим и возвращаетесь в 16-битный реальный режим.Нереальный режим по-прежнему является 16-битным реальным режимом, за исключением того, что ограничения в кэше скрытых дескрипторов установлены в 0xffffffff (предел 4 ГБ).Вернувшись в 16-битный реальный режим, вы сможете напрямую обращаться к памяти в сегментах за пределами 64 КБ, используя 32-битную адресацию, но код все еще работает в 16-битном реальном режиме.
Если вы пишетекод для 16-битного нереального режима ваш компилятор и ассемблер все еще должны генерировать 16-битный код.Если вы намереваетесь написать / сгенерировать 32-битный код, тогда нереальный режим не подходит, и вам потребуется войти в 32-битный защищенный режим для выполнения 32-битного кода.