Estas leyendo el salto de linea y usandolo en los calculos.
Primera iteracion del bucle, en tab tenemos:
0x32 y 0x0A
mov ax, [tab]
sub ax, '0'
mul edi
push ax
AX es primero 0x0A32
Al restarle '0' es 0x0A02
multiplicar por 1 no cambia nada
Asi que empujas en la pila 0x0A02
Segunda iteracion del bucle, mismo valor en tab:
AX es primero 0x0A32
Al restarle '0' es 0x0A02
Al mutiplicarlo por 2 AX es 0x1404
Asi que empujas en la pila 0x1404
Tenes exactamente el mismo error de logica al comparar, si aprieto 4 y enter, en res habra esto:
0x34 y 0x0A
mov cx, word ptr [res]
sub cx, '0'
pop ax
cmp ax, cx
De casualidad te funciona en la primera iteracion:
CX es primero 0x0A32
Al restarle '0' es 0x0A02
Coincide con el resultado errado que empujaste en la pila.
En la segunda iteracion:
CX es primero 0x0A34
Al restarle '0' es 0x0A04
0x1404 no es igual a 0x0A04.
Llegados a este punto es imperativo que logres depurar tu programa linea por linea, entiendo que estas usando Linux (yo uso Windows asi que adapte tu codigo a MASM, con todo lo que eso significa partiendo de que los saltos de linea son \r\n y no \n solo como en Linux y las llamadas a la interrupcion 80h tienen que se reemplazadas por las APIs de Windows) asi que busca algun tutorial sobre gdb.