【发布时间】:2012-02-25 02:54:09
【问题描述】:
我正在忙着做家庭作业,希望得到一些指导。该分配要求您将任意基数的 ASCII 字符串转换为任意基数输出。当我调用 AsciiToDigit 过程(嵌套在 ReadInteger 过程中)时程序挂起,我不知道为什么。调试器没有任何帮助,因为当它到达程序的那个部分时它什么都不做,只是挂起。
我相当确定我需要先将字符转换为数字才能正确执行此操作,但也许我遗漏了一些东西。感谢任何人都可以提供的任何帮助。
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
【问题讨论】:
-
将
add eax, 30h更改为add eax, '0'会大大提高代码的可读性。另外,也许add eax, '30'应该是add eax, '0'。 -
非常感谢您。不过还是挂了。
-
ReadChar 是否在 EAX 中返回结果? WriteChar 是否保留 EAX? AsciiToDigit 显然期望 EAX 中的结果,因此请检查该假设。如果您的调试器没有帮助,请删除行直到它工作。删除 WriteChar。将 ReadChar 替换为对 EAX 的简单赋值(假装您调用了该函数并获得了良好的输入)。跳过对 AsciiToDigit 的调用。修剪你的程序,直到它工作。此外,您应该记录“为什么”,而不是“什么”。像“将 ebx 向左移一个”这样的评论是没有用的,因为很明显
shl ebx, 1做了什么。但是为什么你将 ebx 左移 1? -
建议:更好地格式化代码。将每个子任务分解成尽可能小的部分(子例程),并使每个子例程尽可能短。对模块中的相关小节进行分组。不要用不必要的 cmets 分散代码。使用成熟的calling convention 而不是任意寄存器滥用。
标签: assembly x86 ascii masm irvine32