A priori, c'est parce que AH ne vaut pas 0. Donc fait plûtot un IN AL, DX.
Qui plus est, tu as 2 instructions de saut (JNZ et JMP) là où tu pourrais n'en avoir qu'une.
MOV DX,60h
boucle:
IN AL,DX
CMP AX,1h ; "DEC AX" irait plus vite ici...
JNZ boucle
ret
Bon, tout ça reste bien sûr une méthode très "primitive" de fonctionner (ça bouffe un max de temps CPU au lieu d'attendre une interruption déclenchée par le clavier, et ça risque de cours-circuiter le vrai handler clavier), mais pour du code écrit au bout de 2 semaines, c'est déjà pas mal.