2017-05-24 4 views
0

J'avais prévu de soumettre un interpréteur court et rapide pour ;# dans DOS comme un défi de golf de code, quand j'ai découvert que DOS n'a pas interprété le # Clé correctement.Pourquoi DOS ne gère pas '#' correctement (INT 21/AH = 01h)

Il est probablement préférable de commencer à disséquer via un exemple plus petit qui présente aussi le comportement:

org 0x100 
L: 
    mov ah, 01h  ; new input -> al 
    int 21h 
test al, '#'  ; check if the hash key was pressed 
jnz end   ; if it wasn't, jump to the end of program 
    mov dl, '1' 
    mov ah, 02h 
    int 21h   ; otherwise, output `1` 
    jmp L   ; and loop to the beginning 
end: 
    mov ah, 00h  ; end the program 
    int 21h 

Saisie # dans le programme, va l'amener à tester comme faux, et passer à la fin. Comme le feront la plupart des autres personnages. Toutefois, lorsque j'entre un ou plusieurs des caractères suivants: D, L, H, X, il génère 1 et des boucles. Ce n'est évidemment pas ce qui était prévu.

Il est probablement important de noter que j'ai utilisé Dosbox pour le test.

De test, il se produit pour '#', 0x23, 0x01, 0x1b (Les deux derniers étaient scancodes de la page deux this pdf, trouvé par une recherche aléatoire).

Que se passe-t-il exactement ici?

+0

Quelle est la valeur de 'al' lorsque vous ne saisissez' '#? Les Scancodes de Keryboard ne correspondent pas nécessairement à l'encodage du même caractère, en particulier avec les clés étendues. –

+0

Après 'xor''ing' ah' out, debugx me dit 'ax' est' 0x0023'. C'est en partie pourquoi je suis si perplexe. –

+0

Hmm, je suis allé sur ce sujet précis dans une question similaire (https://stackoverflow.com/a/15182488). Essentiellement, vous utilisez abusivement les instructions 'test' et' jnz'. Ils ont des utilisations très spécifiques et votre interprétation de la façon dont ils devraient se comporter n'est pas correcte. –

Répondre

2

test a,b calcule le bitwise et de a et b, définit les indicateurs et rejette les résultats. test peut en général pas être utilisé pour comparer deux valeurs pour l'égalité, utilisez cmp à cette fin:

cmp al, '#' 
+0

Cela ne répond pas à la question, étant donné que: A) 'test' fonctionne parfaitement bien pour comparer tous les autres caractères que je lui ai lancés (il détecte celui qui a été pressé égal à' cmp'), et B) le modifier pour utiliser 'cmp' ne résout pas le problème. –

+0

Vous pouvez lire [this] (https://stackoverflow.com/questions/13064809/the-point-of-test-eax-eax) pour la différence entre 'test' et' cmp' (il n'y a qu'un différence marginale) –

+2

@ FinnO'leary Si cela fonctionne "bien", alors vous avez fait quelque chose de mal. 'test' ne renvoie que zéro, quand aucun bit n'est défini dans le bitwise et des deux arguments, ce qui n'est généralement pas le cas si les deux sont égaux (c'est-à-dire, sauf si les deux sont nuls). Vous semblez avoir fait une sorte d'erreur ailleurs. – fuz