Сразу отмечу, что с официальной информацией не густо.
На опыте, на практике такая проблема возникла только на Фениксах. Конечно, у меня было мало разных железок за всё время, но факт есть факт.
Есть ABI-стандарт и соглашение, где у всех чётко прописано значение 0 по дефолту и рекомендация обнулять флаг направления при выходе из каждой функции. Об этом есть в System V Intel386 ABI (Registers and the Stack Frame), AMD64 ABI и в других документах и почти на всех форумах. Найти оф. описание, касаемо выставленного флага, Фениксов мне не удалось, зато есть множество тем, где люди с этим сталкивались. Чтобы понять, что проблема длится достаточно давно, я приведу
эту ссылку и цитату:
Years ago, I worked for Tandy when they built their first AT compatible. I had written a disk drive diagnostic that ran fine on a real AT but hung up every time I ran it on our prototype (which worked fine otherwise, including running DOS). We traced the problem to the fact that the BIOS that Tandy licensed from Phoenix (also at an early revision level) used a series of string moves without clearing the direction flag, and my diagnostic happened to set the flag in a display routine. Somebody tried to argue that maybe DOS expected the flag to be cleared at all times. But they couldn't produce any documentation, and besides we could see where the IBM BIOS used a similar series of string moves and did establish the state of the direction flag first, so Phoenix added it. Presumably, Phoenix used a "cleanroom" system: one group of software engineers studied the IBM BIOS source code (which IBM published) and wrote a specification which was then designed and coded by another group of programmers.
Posted by Ellis Easley on 25 Sept 2003, 5:13 p.m.
Соответственно нужно смотреть исходники IBM BIOS и ожидать там такой же проблемы. А пока же мой практический опыт показывает: добавляем cld и всё работает, убираем - и ничего (в лучшем случае, экран пустой чёрный с мигающей кареткой ввода).
Про догадки об умном BIOS'е:
https://stackoverflow.com/questions/392 ... 3#39248323
Так же видел это в каком-то оф. документе, но не сохранил - найду скину ссылку сюда.
Цитата:
In theory you wouldn't need a BPB when writing a MBR and not a VBR, and the presence of the xor ax, ax instruction wouldn't influence the booting.
You should include a xor bh, bh however (more on Int 10/AH=0Eh)
Sadly this is just theory.
Specially for USB devices a BPB is implicitly assumed by some firmware, including the full FDC descriptor (with a valid OS name).
Many thanks to Michael Petch for stressing this out.
Since the introduction of UEFI implementations, particularly the parts dealing with CSM (Compatibility Support Module), i.e. legacy booting, writing a fully supported MBR has became tricky.
The firmware will sometimes try to automatically detect what boot mode to use and since all UEFI devices are also legacy devices per specification, the firmware must rely on some quirk to tell them apart.
My firmware detect a device as "legacy", even when explicitly told so, only when at least one of these is true:
There is a bootable, non empty, partition in the MBR partition table.
The starting/ending address, either in CHS or LBA, are not checked at all.
The first instruction is a xor ax, ax (in either forms: 33 C0 or 31 C0). This is because the first thing most bootloaders do is to set the segment registers to zero through AX.
There may be other "signatures", like a jump at the first bytes, but I haven't tested them (yet).
If the firmware fails to detect the device as legacy and it is not a UEFI compliant device, it will be skipped.
Posted by Margaret Bloom
По немаскируемым прерываниям и магии при изменении сегментных регистров ещё большая каша. Я просто приведу несколько ссылок:
Ссылка:
https://dev64.wordpress.com/2012/05/14/ ... reference/
Цитата:
Дополнительная информация для обработки исключения
Особенное внимание должно быть уделено тому, чтобы исключение возникающее в процессе явного переключения стека не приводила к использованию процессором invalid stack pointer (CS:ESP). Программы, написанные для 16-ти битных IA-32 процессоров часто используют пару инструкций для переключения на новый стек, например:
MOV SS, AX
MOV SP, StackTop
При выполнении этого кода на одном из 32-битных IA-32 процессоров, возможно получить page fault, general protection fault (#GP) или aligment check fault (#AC) исключения после загрузки сегментного селектора в регистр SS, но прежде загрузки регистра SP значением нового StackTop. В этот момент пара SS:ESP является нецелостной. Новый стековый сегмент, и старое значение ESP (stack pointer).
...
В системах, обрабатывающих page-fault, general-protection или aligment check исключения внутри задачи генерирующей fault (с помощью trap или interrupt gate), программа выполняющаяся на том же уровне привелегий, что и обработчик исключения, должна инициализировать новый стек используя LSS инструкцию, вместо пары MOV инструкций, приведенных выше.
Ссылка:
https://c9x.me/x86/html/file_module_x86_id_304.html
Ссылка:
http://www.vcfed.org/forum/archive/inde ... 41453.html
Ссылка:
https://web.itu.edu.tr/kesgin/mul06/int ... r/mov.html
Цитата:
If the destination is SS interrupts are disabled except on early buggy 808x CPUs. Some CPUs disable interrupts if the destination is any of the segment registers
Если кратко, то есть около 4 типажей процессоров, которые по-разному относятся к этой последовательности инструкций.