Какую машинную инструкцию процессора 8086 оказалось сложнее всего воспроизвести? Ни за что не угадаете: команду DAA, десятичную коррекцию для сложения. И парную ей DAS, для вычитания. Ни один из симуляторов процессора не умеет выполнять её аутентичным образом. Я проверил несколько: DOSBox, PCre, MAME. Глядел исходники - везде сделано как в 386, а не как в 8086. Никто так и не озадачился выяснить, как же эти команды работают в реальности.
Пришлось наваять тестик на Турбо Си и прогнать со всеми возможными входами на реальной XT-шке.
Начиная с 286 процессора Интел изменил реализацию команд DAA и DAS. Вот аналогичный результат, полученный на современном Intel Core I7: daa-das-286.txt
Сравниваем:
Пришлось наваять тестик на Турбо Си и прогнать со всеми возможными входами на реальной XT-шке.
Результат - полная таблица "истинности" для команд DAA и DAS процессора 8086 - выложена здесь: daa-das-8086.txtvoid daa(int al_in, int af_in, int cf_in, int *al_out, int *af_out, int *cf_out)
{
int flags_in = (af_in ? 0x10 : 0) | (cf_in ? 1 : 0);
int flags_out = 0;
int al_buf = 0;
asm {
mov al, byte ptr al_in
mov ah, byte ptr flags_in
sahf
daa
lahf
mov byte ptr flags_out, ah
mov byte ptr al_buf, al
}
*al_out = al_buf;
*af_out = (flags_out >> 4) & 1;
*cf_out = flags_out & 1;
}
Начиная с 286 процессора Интел изменил реализацию команд DAA и DAS. Вот аналогичный результат, полученный на современном Intel Core I7: daa-das-286.txt
Сравниваем:
По этим данным удалось построить адекватный код на Си: для DAA и для DAS.DAA:
AL AF CF ---86--- ---286---
9A 1 0 -> A0 1 0 00 1 1
9B 1 0 -> A1 1 0 01 1 1
9C 1 0 -> A2 1 0 02 1 1
9D 1 0 -> A3 1 0 03 1 1
9E 1 0 -> A4 1 0 04 1 1
9F 1 0 -> A5 1 0 05 1 1
DAS:
AL AF CF ---86--- ---286---
00 1 0 -> FA 1 0 FA 1 1
01 1 0 -> FB 1 0 FB 1 1
02 1 0 -> FC 1 0 FC 1 1
03 1 0 -> FD 1 0 FD 1 1
04 1 0 -> FE 1 0 FE 1 1
05 1 0 -> FF 1 0 FF 1 1
9A 1 0 -> 94 1 0 34 1 1
9B 1 0 -> 95 1 0 35 1 1
9C 1 0 -> 96 1 0 36 1 1
9D 1 0 -> 97 1 0 37 1 1
9E 1 0 -> 98 1 0 38 1 1
9F 1 0 -> 99 1 0 39 1 1

no subject
Date: 2026-02-10 04:16 (UTC)no subject
Date: 2026-02-10 04:25 (UTC)no subject
Date: 2026-02-10 04:56 (UTC)void SetBcdFlags() { dst = AL; E.IsByte = true; SetSZP(); } public void C_Daa() { if (AF = (AL & 0xF) > 9 || AF) AL += 6; if (CF = AL > 0x9F || CF) AL += 0x60; SetBcdFlags(); } public void C_Das() { if (AF = (AL & 0xF) > 9 || AF) AL -= 6; if (CF = AL > 0x9F || CF) AL -= 0x60; SetBcdFlags(); }Похоже, но надо проверить по таблице истинности.
no subject
Date: 2026-02-10 05:29 (UTC)no subject
Date: 2026-02-10 07:53 (UTC)DAA оказалась самой сложной в реализации у меня в эмуляторе i8080.
И не потому, что я не мог закодить по спецификации Интела. А потому, что спецификации не давала полного описания, в особенности в плане флагов.
Народ таки прояснил, как оно работает, просто тестируя реальные камни.
Причем, есть известная мулька про i8080 от AMD, где DAA выставляет один флаг иначе.
Потом появились фото-реверсы кристаллов, что подтвердило алгоритм.
Благо для z80/i8080 тоже есть волшебный тест z80 exerciser, который все показывает.
https://github.com/begoon/i8080-js/blob/985436000bda8ddcaf761d849f8a0624e8628be6/i8080.js#L480
no subject
Date: 2026-02-10 10:50 (UTC)Интересное название tiltti... Это что-то значит? У меня эмулятор собрался, но не запустился с 360К образом - Error: Unimplemented: Read sectors (CHS)