2012-02-25 177 views
0

我有一段時間做作業,很喜歡一些指導。該任務要求您將任何基數的ASCII字符串轉換爲任意基數。當我調用AsciiToDigit過程(嵌套在ReadInteger過程中)時,程序掛起,我找不到原因。調試器沒有任何幫助,因爲它不會執行任何操作,而只會在程序的該部分掛起。x86將ASCII字符轉換爲數字

我相當肯定我需要將字符轉換爲數字先做正確的,但也許我失去了一些東西。感謝任何人都可以提供的幫助。

TITLE MASM Template      (main.asm) 

; Description: 
; 
; Revision date: 

INCLUDE Irvine32.inc 
.data 
basePrompt BYTE "What base (2-16 or 0 to quit): ",0 
numPrompt BYTE "Number please: ",0 
invalid BYTE "Invalid base, please try again.",0 
base2 BYTE "Base 2: ",0 
base8 BYTE "Base 8: ",0 
base10 BYTE "Base 10: ",0 
base16 BYTE "Base 16: ",0 
base DWORD 0 


.code 
main PROC 
     call Clrscr 
    State0:        ; initial state to accept base number 
     mov edx, OFFSET basePrompt 
     call ReadBase 
     cmp al, '0'      ; check if 0 entered  
     je ProgEnd      ; jump to ProgEnd if 0 entered 
     mov base, ebx 
     mov edx, OFFSET numPrompt 
     call WriteString 
     call ReadInteger 

     mov ebx, 2 
     mov edx, OFFSET base2 
     call WriteString 
     call WriteInteger 
     mov ebx, 8 
     mov edx, OFFSET base8 
     call WriteString 
     call WriteInteger 
     mov ebx, 10 
     mov edx, OFFSET base10 
     call WriteString   
     call WriteInteger 
     mov ebx, 16 
     mov edx, OFFSET base16 
     call WriteString 
     call WriteInteger 


     call Crlf 
     jmp State0      ; jump back to beginning of program 

    ProgEnd:       ; jump point to end of programt 

    exit 
main ENDP 

;----------------------------------------------------- 
ReadInteger PROC 
; 
; ReadInteger is passed one argument in bl representing the base of the number to be input. 
; Receives: bl register 
; Returns: EAX 
;----------------------------------------------------- 
nextChar: 
    call ReadChar   ; Get the next keypress 
    call WriteChar   ; repeat keypress 
    call AsciiToDigit  
    shl ebx,1   ; shift to make room for new bit 
    or ebx,eax   ; set the bit to eax 
    cmp al, 13    ; check for enter key 
    jne nextChar 
    ret 
ReadInteger ENDP 

;----------------------------------------------------- 
WriteInteger PROC 
; 
; Will display a value in a specified base 
; Receives: EAX register (integer), bl (base) 
; Returns: nothing 
;----------------------------------------------------- 

    mov ecx, 0   ;count the digits 
nextDigit: 
    mov edx, 0   ;prepare unsigned for divide 
    div ebx 
    push edx   ;remainder will be in dl 
    inc ecx   ;count it! 
    cmp eax,0   ;done when eax becomes 0 
    jne nextDigit 

;now the digits are on the stack 
;pop them off and convert to ASCII for output 
outDigit: 
    pop eax    ;digits come off left to right 
    add eax, '30'  ;add 0011 to front to get ASCII 
    call WriteChar 
    loop outDigit 

    call Crlf 
    ret 



    ret 
WriteInteger ENDP 

;----------------------------------------------------- 
ReadBase PROC 
; 
; Prompts the user for input and stores input into EAX. 
; Receives: EDX register 
; Returns: EAX 
;----------------------------------------------------- 
    Call WriteString 

    xor ebx, ebx    ; clear ebx 
     call ReadChar 
     call WriteChar 
     cmp al, '0' 
     je Done 
     cmp al, 13    ; look for return carriage, jump to end 
     je Done 
     mov ebx, eax 
     shl ebx, 1    ; shift ebx left one 
     call ReadChar 
     call WriteChar 
     or ebx, eax 

    Done: 
     call Crlf 
    ret 
ReadBase ENDP 

;----------------------------------------------------- 
AsciiToDigit PROC 
; 
; This procedure receives the ASCII code of a digit and returns the numerical digit value. 
; Receives: EAX register 
; Returns: EAX 
;----------------------------------------------------- 
    cmp eax, 61h 
    jb Upper 
    sub eax,61h 
    jmp done 

    Upper: 
     cmp eax, 41h 
     jb Digit 
     sub eax, 41h 
     jmp done 

    Digit: 
     sub eax,30h 

    done: 
     ret 
AsciiToDigit ENDP 

;----------------------------------------------------- 
DigitToAscii PROC 
; 
; This procedure receives digit and returns Ascii value 
; Receives: EAX register 
; Returns: EAX 
;----------------------------------------------------- 
    add eax, 30h 

    ret 
DigitToAscii ENDP 
END main 
+2

將'add eax,30h'改爲'add eax','0''會改善代碼的可讀性。另外,也許'add eax','30'應該是'add eax','0''。 – AusCBloke 2012-02-25 03:05:21

+0

謝謝你非常好。儘管如此。 – 2012-02-25 03:14:34

+0

ReadChar是否將結果返回給EAX? WriteChar保存EAX嗎? AsciiToDigit顯然期望EAX中的結果,因此請檢查該假設。如果你的調試器沒有幫助,刪除線路直到它工作。刪除WriteChar。將ReadChar替換爲EAX的簡單賦值(假設您調用該函數並獲得了很好的輸入)。跳過對AsciiToDigit的呼叫。修剪你的程序,直到它工作。此外,你應該記錄「爲什麼」,而不是「什麼」。像「shift ebx left one」這樣的評論是無用的,因爲它清楚'shl ebx,1'的作用。但是*爲什麼*你將ebx左移1? – indiv 2012-02-25 05:17:39

回答

0

到目前爲止我還能看到一些東西。

在第一部分中,當您嘗試獲取基數時,如果輸入10,代碼將退出。我認爲你需要查看每個字符,因爲它是從用戶輸入的。

接下來,你是掛着的,因爲程序似乎正在繼續通過獲取數字,而你正在讀取該特定基地的整數。在這一點上,代碼:

;----------------------------------------------------- 
; AsciiToDigit PROC 
; 
; This procedure receives the ASCII code of a digit and returns 
; the numerical digit value. 
; Receives: EAX register 
; Returns: EAX 
;----------------------------------------------------- 
cmp eax, 61h 
jb Upper 
sub eax,61h 
jmp done 

當您從EAX減去61H,如果該人已點擊「進入」,即價值消失。含義13h將被減去61h,使AL保留在ACh。所有這一切意味着只要代碼連續減去61h,就永遠不會看到輸入13h。

我想你可能想放些更多的cmp,並且在這方面真的考慮更多的代碼。另外,要小心你推入並彈出到堆棧。觀看寄存器並查看它們在執行這些功能時的作用。

只是看一些事情,希望它有幫助。