-1

学校での最終課題としてコードを作成しました... ログインフォームです。登録とログインはできますが、私が見つけた唯一のバグは、16 桁のパスワードを入力できないことです。

プログラムで修正または改善できる点について、フィードバックをお寄せください。

前もって感謝します。

 .MODEL small
.STACK 100h
.DATA
 uinp db 13, 0, 14 DUP('$')  ; Username register input, max 12 letters                    ;
 pinp db 17, 0, 16 DUP('$')  ; Password register input, max 16 letters

 ulinp db 13, 0, 14 DUP('$') ; Username login input
 plinp db 17, 0, 16 DUP('$') ; Password login input

 wlmsg db "        Welcome user!        ", 10, 13, "$"      ;     
 wlmsg2 db "        Please login...        ", 10, 13, "$"   ; Welcome messages
 wlmsg3 db "        Press any key..        ", 10, 13, "$"   ;

 umsg db "        Username:         ", 10, 13,       ;
 db "        Password:         $", 10, 13,       ; Username and password text

 question db "        Would you like to               ", 10, 13   ;
     db   "        (R) Register               ", 10, 13      ; Main menu text
     db   "        (L) Login               ", 10, 13         ;
     db   "           ( )               $", 10, 13           ;

 errormsg db "           ERROR!        ", 10, 13          ;
  db "     Please make sure you        ", 10, 13     ;
  db "   followed the instructions        ", 10, 13  ;   Error message                ; JUST TO CLARIFY:
  db "     and wrote your choice        ", 10, 13    ;                                ; At first I wanted to create a file, write the username and password onto it 
  db "      with CAPITAL LETTERS        $", 10, 13   ;                                ; and then read it. Turn's out that it was out of the course scope and it's not
                                                                                      ; critical for the program.  

 errormsg2 db "     username or password are incorrect ", 10, 13      ; Second error message
      db "            try again later... $"

 afterRegisterMsg db "        Nice, now go back to menu $", 10, 13    ; After registration message

 sLogin db "                                    ", 10, 13 
   db "        ********************************* ", 10, 13
   db "        *You have succesfully logged in!* ", 10, 13 ; Message after      succesful match to the user name and password 
   db "        *********************************$", 10, 13
 choice db ' '      ;o Choice of user in menu    

 fLogin db "       Username and password are incorrect.",10 ,13   ; Fail to login message
   db "        Please try again and make sure", 10, 13
   db "         enterd the right username and", 10, 13
   db "                   password.         $", 10, 13

 .CODE                                                        

mov ax, @data                   
mov ds, ax                                   


 Welcome:
mov dx, offset wlmsg   ; First message
mov ah, 09h
int 21h

mov dx, offset wlmsg2  ; Second message
mov ah, 09h
int 21h

mov dx, offset wlmsg3 ; Third message
mov ah, 09h
int 21h

mov ah, 01h   ; Wait for user to continue
int 21h       ;

call clear    ; Clear screen


 Menu:
call clear              ; Clear screen

mov dx, offset question ;
mov ah, 09h             ;  Print menu
int 21h                 ;

mov dh, 03h        ;
mov dl, 12         ;
mov bh, 0          ; Set cursor to (12,3)
mov ah, 02h        ; 
int 10h

mov ah, 01h             ; 
int 21h                 ; Reads user's choice         


cmp al, 'R'    ;  Check if user picked register option

je Register           ; Jump to 1register label

cmp al, 'L'    ;  Check if user picked login option

je Login             ; Jump to login label
jmp Error 


 Error:
call clear

mov dx, offset errormsg  ;
mov ah, 09h              ;  Print error message
int 21h                  ; 

mov ah, 08h   ; Wait for user to continue
int 21h       ;


 jmp Menu                 ; Jump back to menu


 Register:
call clear           ; Clear screen

mov dx, offset umsg  ;
mov ah, 09h          ; Print username 
int 21h              ;           

mov dx, 18        ;
mov bh, 0         ; Set cursor to (18,0)
mov ah, 02h       ; 
int 10h

mov dx, offset uinp ;
mov ah, 0Ah         ; Read username input and puts it into uinp
int 21h             ;

mov dh, 01h       ;
mov dl, 18        ;
mov bh, 0         ; Set cursor to (18,1)
mov ah, 02h       ; 
int 10h

mov dx, offset pinp     ;
mov ah, 0Ah             ; Reads password input and puts it into pinp
int 21h                 ;

call clear

mov dx, offset afterRegisterMsg    ;
mov ah, 09h                        ;  Print after registration message
int 21h                            ;

mov ah, 01h                        ; Waits for user to click a button
int 21h                            ;

jmp menu                     ; Go back to menu

 Login: 
call clear               ; Clear screen

mov dx, offset umsg    ;
mov ah, 09h            ;   Prints username and password
int 21h                ;

mov dx, 18        ;
mov bh, 0         ; Set cursor to (18,0)
mov ah, 02h       ; 
int 10h

mov dx, offset ulinp  ;
mov ah, 0Ah           ;   Reads username login input 
int 21h               ;

mov dh, 01h       ;
mov dl, 18        ;
mov bh, 0         ; Set cursor to (18,1)
mov ah, 02h       ; 
int 10h

mov dx, offset plinp  ;
mov ah, 0Ah           ;   Reads password login input 
int 21h               ;

call chkLength ; Match length

mov dx, 0      ;
mov cx, 0      ;  Reset all the registers for compUser
mov ax, 0      ;

jmp CompareU  ; Check if username is correct 

 hlt


 chkLength:           ;

mov dh, [uinp + 1]   ; Finding the length of the username that the user have enterd
mov dl, [ulinp + 1]  ; "                                     "                    "

cmp dh, dl           ; Comparing their lengths

jne Error2           ; If their lengths aren't equal there will be an error

mov dh, [pinp + 1]   ; Finding the length of the password that the user have enterd
mov dl, [plinp + 1]  ; "                                     "                    "

cmp dh, dl           ; Comparing their lengths

jne Error2           ; Error if the strings don't have the same lengths

ret                  ; Go back to the login main


 Error2:             ; After comparing error

call clear      ; call clear

mov dx, offset errormsg2     ;
mov ah, 09h                  ; Error in case the user entered wrong username and password
int 21h                      ; 

mov ah, 01h     ; Wait for click
int 21h         ;

call clear      ; Clear screen
int 20h         ; End the program          


 CompareU:           ; Comparing the usernames 

mov dh, offset uinp ; Get uinp address
add dh, 2       ; Add 2 to skip to the actaul string

mov dl, offset ulinp  ; Get ulinp address
add dl, 2       ; Add 2 to skip to the actaul string

add dh, cl      ; Adding the index to the address so it can know what character to go through
add dl, cl      ; "                                                                         "

push cx         ; Maintaining the index count

mov bh, 0       ;
mov bl, dh      ; Going into the memory to get uinp actaul string
mov ch, [bx]    ;

mov bh, 0       ;
mov bl, dl      ; Going into the memory to get ulinp actaul string
mov cl, [bx]    ;

cmp cl, ch      ; Comparing the two usernames     

jne Error2      ; If the usernames are not the same it sum as an error

mov bh, 0       ; 
mov bl, dh      ; 
mov al, [bx]    ; Cheking if the string ended
cmp al, '$'     ; 

je resetReg     ; Reset all the registers for the password compare

pop cx          ; Pop the index back out again so it could be increased

inc cl          ; Increase the index by 1 to go over the next charachter 

jmp CompareU    ; Jump back again to the head of the label to check all over again


 resetReg:           ; Reset registers label 

mov ax, 0       ; Reset ax
mov bx, 0       ; Reset bx
mov cx, 0       ; Reset cx
mov dx, 0       ; Reset dx

jmp CompareP    ; Go to the password comparing


 CompareP:           ; Comparing the passwords

mov dh, offset pinp    ; Get pinp address
add dh, 2       ; Add 2 to skip to the actaul string

mov dl, offset plinp   ; Get plinp address
add dl, 2       ; Add 2 to skip to the actaul string

add dh, cl      ; Adding the index to the address so it can know what character to go through
add dl, cl      ; "                                                                         "

push cx         ; Maintaining the index count

mov bh, 0       ;
mov bl, dh      ; Going into the memory to get pinp actaul string
mov ch, [bx]    ;

mov bh, 0       ;
mov bl, dl      ; Going into the memory to get plinp actaul string
mov cl, [bx]    ;

cmp cl, ch      ; Comparing the two passwords     

jne Error2      ; If the passwords are not the same it sum as an error

mov bh, 0       ;
mov bl, dh      ;
mov al, [bx]    ; Cheking if the string ended
cmp al, '$'     ;

je successLogin ; Letting the user know that he enterd and both username and password are true

pop cx          ; Pop the index back out again so it could be increased

inc cl          ; Increase the index by 1 to go over the next charachter
jmp CompareP    ; Jump back again to the head of the label to check all over again

 successLogin:       ; Successful login message

call clear      ; Clearing the screen

mov dx, offset sLogin     ; 
mov ah, 09h               ;  Print the successful login message
int 21h                   ;

mov ah, 01h     ; Waiting for the user to make it's final click
int 21h         ;

 int 20h             ; End of the program in case the login was succesful 

 clear:
mov ah, 06h       ;
mov al, 00h       ;
mov bh, 0Fh       ;
mov cx, 0         ; Clear Screen
mov dh, 100       ;
mov dl, 40        ;
int 10h           ;

mov dx, 0         ;
mov bh, 0         ; Set cursor to (0,0)
mov ah, 02h       ; 
int 10h 

ret               ; Return back to where it was called

 int 20h             ; End of program no matter what
4

1 に答える 1

2

しかし、私が見つけた唯一のバグは、16 桁のパスワードを入力できないことです。

パスワードの入力に使用する構造は、一貫性のない設定を使用します。指定したバッファよりも長いバッファを宣言しました!

uinp db 13, 0, 14 DUP('$')  ; Username register input, max 12 letters                    ;
pinp db 17, 0, 16 DUP('$')  ; Password register input, max 16 letters

ulinp db 13, 0, 14 DUP('$') ; Username login input
plinp db 17, 0, 16 DUP('$') ; Password login input

ユーザー名の両方の行は問題ありませんが、パスワードの行18 DUP('$')は代わりに使用する必要があります16 DUP('$')

さらに考慮すべきことは、DOSでは、パスワードに含める拡張文字ごとに 2 バイトが必要になることです。(パスワードでは珍しいことではありません) おそらく、次のように書くことでこれを防ぐことができます:

pinp db 17, 0, 35 DUP('$')  ; Password register input, max 16 letters
plinp db 17, 0, 35 DUP('$') ; Password login input 

プログラムには、次のように書く場所がいくつかあります。

mov dh, offset uinp ; Get uinp address
add dh, 2       ; Add 2 to skip to the actaul string

mov dl, offset ulinp  ; Get ulinp address
add dl, 2       ; Add 2 to skip to the actaul string

これは非常に危険な構造です。
現在のプログラムでは、関連する構造体が .DATA セクションの早い段階で配置されているため、オフセット アドレスの上位バイトがゼロになるため、機能します。これらの入力構造が他のすべてのメッセージの下に配置されるとどうなるかを考えてみてください。確かに大混乱!
OFFSET 演算子で指定された完全な 16 ビット値を使用することをお勧めします。

 CompareU:           ; Comparing the usernames 

mov di, offset uinp ; Get uinp address
add di, 2       ; Add 2 to skip to the actaul string

mov si, offset ulinp  ; Get ulinp address
add si, 2       ; Add 2 to skip to the actaul string

add di, cx      ; Adding the index to the address so it can know what character to go through
add si, cx      ; "                                                                         "

push cx         ; Maintaining the index count

mov ch, [di]    ;
mov cl, [si]    ;
cmp cl, ch      ; Comparing the two usernames     
jne Error2      ; If the usernames are not the same it sum as an error

cmp ch, '$'     ; Cheking if the string ended
je resetReg     ; Reset all the registers for the password compare

pop cx          ; Pop the index back out again so it could be increased

inc cx          ; Increase the index by 1 to go over the next charachter 

jmp CompareU    ; Jump back again to the head of the label to check all over again

前のコードでは、単語サイズの置換のみに焦点を当てていましたが、他にも問題があります。

文字列の終わりが見つかったときに何が起こるか見てください。resetRegラベルにジャンプしますが、スタックには編集されていない CX 値がまだ保持されていますpop。ここでの解決策は、命令と命令の間に命令を配置することpop cxです。命令はどのフラグも変更しないため、これを行うことができます。Error2ラベルにジャンプしても、プログラムは終了するので問題ありません。cmpjepop

cmp ch, '$'     ; Cheking if the string ended
pop cx          ; Pop the index back out again so it could be increased
je resetReg     ; Reset all the registers for the password compare

上記のすべては、 ComparePルーチンにも適用されます。


ここには、コードを最適化する機会がたくさんあります。最終的にはそれが StackOverflow の目的ではないため、1 つだけを示します。

mov ch, [di]    ;
mov cl, [si]    ;
cmp cl, ch      ; Comparing the two usernames 

CL レジスタに転送する代わりに、メモリから直接比較できます。

mov ch, [di]    ;
cmp [si], ch    ; Comparing the two usernames 
于 2016-09-21T10:35:26.307 に答える