; GETI.ASM ; ; This module contains the integer input routine for the matrix ; example in Chapter Eight .nolist include stdlib.a .list include matrix.a InpSeg segment para public 'input' ; Geti- On entry, es:di points at a string of characters. ; This routine skips any leading spaces and comma characters and then ; tests the first (non-space/comma) character to see if it is a digit. ; If not, this routine returns the carry flag set denoting an error. ; If the first character is a digit, then this routine calls the ; standard library routine "atoi2" to convert the value to an integer. ; It then ensures that the number ends with a space, comma, or zero ; byte. ; ; Returns carry clear and value in AX if no error. ; Returns carry set if an error occurs. ; ; This routine leaves ES:DI pointing at the character it fails on when ; converting the string to an integer. If the conversion occurs without ; an error, the ES:DI points at a space, comma, or zero terminating byte. geti proc far ifdef debug print char "Inside GETI",cr,lf,0 endif ; First, skip over any leading spaces or commas. ; Note the use of the "byp" symbol to save having to type "byte ptr". ; BYP is a text equate appearing in the macros.a file. ; A "byte ptr" coercion operator is required here because MASM cannot ; determine the size of the memory operand (byte, word, dword, etc) ; from the operands. I.e., "es:[di]" and ' ' could be any of these ; three sizes. ; ; Also note a cute little trick here; by decrementing di before entering ; the loop and then immediately incrementing di, we can increment di before ; testing the character in the body of the loop. This makes the loop ; slightly more efficient and a lot more elegant. dec di SkipSpcs: inc di cmp byp es:[di], ' ' je SkipSpcs cmp byp es:[di], ',' je SkipSpcs ; See if the first non-space/comma character is a decimal digit: mov al, es:[di] cmp al, '-' ;Minus sign is also legal in integers. jne TryDigit mov al, es:[di+1] ;Get next char, if "-" TryDigit: isdigit jne BadGeti ;Jump if not a digit. ; Okay, convert the characters that follow to an integer: ConvertNum: atoi2 ;Leaves integer in AX jc BadGeti ;Bomb if illegal conversion. ; Make sure this number ends with a reasonable character (space, comma, ; or a zero byte): cmp byp es:[di], ' ' je GoodGeti cmp byp es:[di], ',' je GoodGeti cmp byp es:[di], 0 je GoodGeti ifdef debug print char "GETI: Failed because number did not end with " char "a space, comma, or zero byte",cr,lf,0 endif BadGeti: stc ;Return an error condition. ret GoodGeti: clc ;Return no error and an integer in AX ret geti endp InpSeg ends end