Для всех, кто интересуется 16-разрядным решением x86, здесь есть код JasonKnight здесь 1 (он также содержит подписанную множимую часть, которую я не тестировал). Однако этот код имеет проблемы с большими входами, где часть «добавить bx, bx» будет переполняться.
Фиксированная версия:
softwareMultiply:
; INPUT CX,BX
; OUTPUT DX:AX - 32 bits
; CLOBBERS BX,CX,DI
xor ax,ax ; cheap way to zero a reg
mov dx,ax ; 1 clock faster than xor
mov di,cx
or di,bx ; cheap way to test for zero on both regs
jz @done
mov di,ax ; DI used for reg,reg adc
@loop:
shr cx,1 ; divide by two, bottom bit moved to carry flag
jnc @skipAddToResult
add ax,bx
adc dx,di ; reg,reg is faster than reg,imm16
@skipAddToResult:
add bx,bx ; faster than shift or mul
adc di,di
or cx,cx ; fast zero check
jnz @loop
@done:
ret
Или такая же в встроенной сборке GCC :
asm("mov $0,%%ax\n\t"
"mov $0,%%dx\n\t"
"mov %%cx,%%di\n\t"
"or %%bx,%%di\n\t"
"jz done\n\t"
"mov %%ax,%%di\n\t"
"loop:\n\t"
"shr $1,%%cx\n\t"
"jnc skipAddToResult\n\t"
"add %%bx,%%ax\n\t"
"adc %%di,%%dx\n\t"
"skipAddToResult:\n\t"
"add %%bx,%%bx\n\t"
"adc %%di,%%di\n\t"
"or %%cx,%%cx\n\t"
"jnz loop\n\t"
"done:\n\t"
: "=d" (dx), "=a" (ax)
: "b" (bx), "c" (cx)
: "ecx", "edi"
);
Для любого, кто приезжает сюда и находит что, даже если у них есть пробелы после двоеточия, они все еще получают эту ошибку
, можно также получить эту ошибку при копировании yaml текста с некоторого отформатированного источника (для меня, это было Слабое сообщение). Это невидимо загрузит символы неASCII, которые типичный читатель YAML не может считать, но которые выглядят одинаково.
Решение состоит в том, чтобы только скопировать с сырых данных, источника неASCII.