home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol12n05.zip / NUMBER.ZIP / NUMBER.ASM next >
Assembly Source File  |  1992-04-25  |  3KB  |  163 lines

  1. cseg    segment
  2.     assume cs:cseg, ds:cseg
  3.  
  4. SkipInstruction macro
  5.     db    10111001b
  6. endm
  7. ; 10111001b is a "mov cx, immed" opcode -- it results in the following
  8. ; two bytes being moved to cx, rather than being executed as code.
  9. ; Just a way of avoiding a "jmp short Exit" instruction below (saving
  10. ; a byte each time).
  11.  
  12.     org    100h
  13.  
  14. Start:    cld
  15.     xor    dx,dx        ; initial offset
  16.     mov    si,81h
  17.     call    SkipWhite    ; get first char. after spaces and tabs
  18.     jz    DoIt        ; ... if no options
  19.     cmp    al,"/"        ; valid switch chr?
  20.     je    Option
  21.     cmp    al,"-"
  22.     jne    Help
  23. Option:
  24.     lodsb
  25.     or    al,00100000b    ; force lower case
  26.     cmp    al,"s"
  27.     je    Skip
  28.     cmp    al,"+"
  29.     jne    Help
  30. PlusN:
  31.     call    ToNum        ; get offset
  32.     jc    Help        ; C set if not a number
  33.     jz    TooBig        ; Z set if overflow occurred
  34.     cmp    ax,65000
  35.     jae    TooBig
  36.     mov    dx,ax        ; put offset in dx
  37.     or    ax,ax        ; decrement offset unless it is zero
  38.     jz    DoIt
  39. Skip:
  40.     dec    dx        ; for "SKIP", set dx = -1
  41. DoIt:
  42.     push    dx        ; save offset
  43.  
  44.     mov    ah,3Fh        ; read
  45.     xor    bx,bx         ; from standard input
  46.     mov    dx,offset Buffer ; into Buffer
  47.     mov    cx,65000     ; up to 65000 characters (should be enough!)
  48.     int    21h
  49.  
  50.     mov    cx,ax        ; cx = # of characters read
  51.     pop    ax        ; ax = offset (or SkipFlag)
  52.     sub    cx,2
  53.     jbe    NoInput        ; had to read 3 or more characters
  54.  
  55.     inc    ax        ; Skip?
  56.     jnz    AddOffset
  57.     mov    si,dx        ; dx & si = start of buffer
  58.     mov    di,dx
  59.     add    di,cx        ; di = end of buffer
  60.     mov    byte ptr [di],13 ; make sure we stop at the end
  61. SkipLoop:
  62.     call    SkipChkDigit    ; check if next non-WhtSpc chr is a digit
  63.     jnc    GetNum        ; yes -- OK
  64.     mov    dx,si        ; else save current position
  65.     cmp    si,di        ; and see if we're finished
  66.     jbe    SkipLoop
  67.     jmp    short NoNumber
  68.  
  69. AddOffset:
  70.     dec    ax
  71.     cmp    ax,cx        ; offset > actual number of bytes read?
  72.     jae    TooBig
  73.     add    dx,ax
  74.  
  75. GetNum:
  76.     mov    si,dx
  77.     call    ToNum
  78.     jc    NoNumber    ; carry = no number found
  79.     jz    GrtEq250    ; zero = number bigger than 65535
  80.     cmp    ax,250        ; must be <= 250
  81.     jbe    Exit
  82. GrtEq250:
  83.     mov    al,250        ; greater or equal to 250
  84.     SkipInstruction
  85. NoNumber:
  86.     mov    al,254
  87.     SkipInstruction
  88. TooBig:
  89.     mov    al,253
  90.     SkipInstruction
  91. NoInput:
  92.     mov    al,252
  93.  
  94. Exit:    mov    ah,4Ch
  95.     int    21h
  96.  
  97. Help:    mov    dx,offset HelpMsg
  98.     mov    ah,9
  99.     int    21h
  100.     mov    al,255        ; invalid parameters
  101.     jmp    Exit
  102.  
  103. SkipWhite:
  104.     lodsb
  105.     cmp    al," "
  106.     je    SkipWhite
  107.     cmp    al,9
  108.     je    SkipWhite
  109.     cmp    al,13
  110.     ret
  111.  
  112. SkipChkDigit:
  113.     call    SkipWhite
  114.     dec    si
  115. ChkDigit:
  116.     lodsb
  117.     sub    al,"0"
  118.     jc    ChkDone
  119.     cmp    al,10
  120.     cmc
  121. ChkDone:
  122.     ret
  123.  
  124. ToNum:    call    SkipChkDigit
  125.     jc    NumExit
  126. NumLoop:
  127.     mov    bx,ax
  128.     call    ChkDigit
  129.     jc    NumDone
  130.     cbw
  131.     mov    cx,ax
  132.     mov    al,10
  133.     mul    bx
  134.     jc    Overflow
  135.     add    ax,cx
  136.     jnc    NumLoop
  137. Overflow:
  138.     xor    ax,ax        ; reset C, set Z
  139.     ret
  140.  
  141. NumDone:
  142.     or    al,al        ; reset C, reset Z (al <> 0 here)
  143.     mov    ax,bx
  144. NumExit:
  145.     ret
  146.  
  147. Buffer    equ    $
  148.  
  149. HelpMsg:
  150.  db "Usage: NUMBER [/option]",13,10
  151.  db " reads a number from the keyboard (or a `pipe'), returning",13,10
  152.  db " the result in ERRORLEVEL (EL).  `option' can be:",13,10
  153.  db 9,"+n  (start at the nth character)",13,10
  154.  db 9,"S   (search for the first number in the input)",13,10,10
  155.  db " EL = 250",9,"number was >= 250;",13,10
  156.  db " EL = 252",9,"no input;",13,10
  157.  db " EL = 253",9,"offset too big;",13,10
  158.  db " EL = 254",9,"no number found;",13,10
  159.  db " EL = 255",9,"invalid option (this message displayed).",13,10,10,"$"
  160.  
  161. cseg    ends
  162.     end    Start
  163.