2026-02-09

vak: (Знайка)
Какую машинную инструкцию процессора 8086 оказалось сложнее всего воспроизвести? Ни за что не угадаете: команду DAA, десятичную коррекцию для сложения. И парную ей DAS, для вычитания. Ни один из симуляторов процессора не умеет выполнять её аутентичным образом. Я проверил несколько: DOSBox, PCre, MAME. Глядел исходники - везде сделано как в 386, а не как в 8086. Никто так и не озадачился выяснить, как же эти команды работают в реальности.

Пришлось наваять тестик на Турбо Си и прогнать со всеми возможными входами на реальной XT-шке.
void 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;
}
Результат - полная таблица "истинности" для команд DAA и DAS процессора 8086 - выложена здесь: daa-das-8086.txt

Начиная с 286 процессора Интел изменил реализацию команд DAA и DAS. Вот аналогичный результат, полученный на современном Intel Core I7: daa-das-286.txt

Сравниваем:
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
По этим данным удалось построить адекватный код на Си: для DAA и для DAS.