2012-02-25 184 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,并且在这方面真的考虑更多的代码。另外,要小心你推入并弹出到堆栈。观看寄存器并查看它们在执行这些功能时的作用。

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