home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / BDSC / BDSC-1 / BDSNEW.CSM < prev    next >
Text File  |  2000-06-30  |  15KB  |  544 lines

  1.     title    'BDSNEW - New BDS C Library Functions'
  2.  
  3. ;
  4. ;    BDSNEW - New BDS C Library Functions
  5. ;
  6. ;    File creation date:    April 12, 1982 @ 15:33 by BDR
  7. ;    Last revision date:        new file
  8. ;
  9. ;    Operating System:    CP/M 2.x
  10. ;    Software Revision:    1.0
  11. ;
  12. ;
  13. ;    This file replaces several of the BDS C library functions that were
  14. ;    written in C.  The functions, being written in assembly rather than
  15. ;    C, are much faster than the old functions.  The most impressive speed
  16. ;    increase was found in the 'strcmp' function, which is used fairly often
  17. ;    in many applications.
  18. ;
  19. ;    These functions are believed to accurately replace the corresponding
  20. ;    BDS C functions.  If any bugs are found, please notify me either
  21. ;    through Uucp (ucbvax(shriek)ucivax(shriek)csuf(shriek)bruce), or
  22. ;    through the Garden Grove Data Exchange RCPM system:  (714) 534-1547.
  23. ;    (Gee, I wish MAC allowed exclamation marks in comments...)
  24. ;
  25. ;                Bruce Robertson
  26. ;
  27.     page
  28. ;
  29. ;    Modification History
  30. ;    ====================
  31. ;
  32. ;    July 21, 1982  Modified to include two block move functions MOVE and
  33. ;               MOVDN which assemble with the Z80 move instructions if
  34. ;               the 'z80' equate is true.(Incidently using conditionals
  35. ;               with CASM isn't easy..it doesn't recognize 'if..endifs')
  36. ;              J.R.
  37. ;    July 19, 1982  Modified to be compatible with the CASM preprocessor.
  38. ;                Jack Riley (303) 499-9169 RCPM
  39. ;
  40. ; v1.0        April 12, 1982 @ 13:33 by BDR
  41. ;    Original file was created.
  42. ;
  43.     page
  44.     maclib    bds
  45.     page
  46.  
  47.     z80    equ    1    ; set to 1 only if code used on z80 computer
  48.  
  49. ;
  50. ;    This macro is used with the character argument functions to fetch
  51. ;    the argument from the stack.  The argument is placed into register A.
  52. ;
  53.  
  54. getbyte    macro
  55.     lxi    h,2        ;; load the offset to the argument
  56.     dad    sp        ;; HL now points to the argument
  57.     mov    a,m        ;; fetch the argument from the stack
  58.     endm
  59.     page
  60. ;
  61. ;    Character functions:    isupper(), islower(), isalpha(), isdigit(),
  62. ;                toupper(), tolower(), isspace()
  63. ;
  64. ;    Each of these functions expects a single 'char' as an argument.  The
  65. ;    functions starting with 'is' return either TRUE or FALSE for a given
  66. ;    character argument, depending on the condition the function is testing.
  67. ;    the functions starting with 'to' return a (possibly altered) character.
  68. ;
  69.  
  70.  
  71. ;
  72. ;    Return TRUE if upper case.
  73. ;
  74.  
  75.     FUNCTION    isupper
  76.  
  77.     getbyte            ; fetch the argument from the stack
  78.     lxi    h,0        ; assume that it isn't upper case
  79.     cpi    'A'        ; can't be lower than an A...
  80.     rc            ; return with FALSE if it is
  81.     cpi    'Z'+1        ; can't be greater than a Z...
  82.     rnc            ; return with FALSE if it is
  83.     inr    l        ; change the result to TRUE
  84.     ret            ; return to caller
  85.  
  86.     ENDFUNC isupper
  87.  
  88.  
  89. ;
  90. ;    Return TRUE if lower case.
  91. ;
  92.  
  93.     FUNCTION    islower
  94.  
  95.     getbyte            ; fetch the argument from the stack
  96.     lxi    h,0        ; assume that it isn't lower case
  97.     cpi    'a'        ; can't be lower than an 'a'...
  98.     rc            ; return with FALSE if it is
  99.     cpi    'z'+1        ; can't be greater than a 'z'...
  100.     rnc            ; return with FALSE if it is
  101.     inr    l        ; change the result to TRUE
  102.     ret            ; return to caller
  103.  
  104.     ENDFUNC islower
  105.  
  106.  
  107. ;
  108. ;    Return TRUE if upper or lower case.
  109. ;
  110.  
  111.     FUNCTION    isalpha
  112.  
  113.     getbyte            ; fetch the argument from the stack
  114.     lxi    h,0        ; assume that it isn't alphabetic
  115.     ani    0DFh        ; if lower case, convert to upper case
  116.     cpi    'A'        ; can't be lower than an A...
  117.     rc            ; return with FALSE if it is
  118.     cpi    'Z'+1        ; can't be larger than a Z...
  119.     rnc            ; return with FALSE if it is
  120.     inr    l        ; change the result to TRUE
  121.     ret            ; return to caller
  122.  
  123.     ENDFUNC isalpha
  124.  
  125.  
  126. ;
  127. ;    Return TRUE if digit.
  128. ;
  129.  
  130.     FUNCTION    isdigit
  131.  
  132.     getbyte            ; fetch the argument from the stack
  133.     lxi    h,0        ; assume that it isn't a digit
  134.     cpi    '0'        ; can't be lower than a zero...
  135.     rc            ; return FALSE if it is
  136.     cpi    '9'+1        ; can't be larger than a nine...
  137.     rnc            ; return FALSE if it is
  138.     inr    l        ; change the result to TRUE
  139.     ret            ; return to caller
  140.  
  141.     ENDFUNC isdigit
  142.  
  143.  
  144. ;
  145. ;    Convert to upper case if lower case.
  146. ;
  147.  
  148.     FUNCTION    toupper
  149.  
  150.     getbyte            ; fetch the argument from the stack
  151.     mov    l,a        ; assume that the character isn't lower case
  152.     mvi    h,0        ; (this is placing the character into HL)
  153.     cpi    'a'        ; can't be lower than an 'a'...
  154.     rc            ; return with the original character if it is
  155.     cpi    'z'+1        ; can't be larger than a 'z'...
  156.     rnc            ; return with the original if it is
  157.     ani    05Fh        ; it's lower case - convert to upper case
  158.     mov    l,a        ; put the new character into HL
  159.     ret            ; return to caller
  160.  
  161.     ENDFUNC toupper
  162.  
  163.  
  164. ;
  165. ;    Convert upper case to lower case.
  166. ;
  167.  
  168.     FUNCTION    tolower
  169.  
  170.     getbyte            ; fetch the argument from the stack
  171.     mov    l,a        ; assume that the character isn't upper case
  172.     mvi    h,0        ; (this is placing the character into HL)
  173.     cpi    'A'        ; can't be lower than an A...
  174.     rc            ; return with the original character if it is
  175.     cpi    'Z'+1        ; can't be larger than a Z...
  176.     rnc            ; return with the original if it is
  177.     ori    020h        ; it's upper case - convert to lower case
  178.     mov    l,a        ; put the new character into HL
  179.     ret            ; return to caller
  180.  
  181.     ENDFUNC tolower
  182.  
  183.  
  184. ;
  185. ;    Return TRUE if character is a space, tab or newline.
  186. ;
  187.  
  188.     FUNCTION    isspace
  189.  
  190.     getbyte            ; fetch the argument from the stack
  191.     lxi    h,1        ; assume that it is a white space character
  192.     cpi    ' '        ; check for a space
  193.     rz            ; return if we have one
  194.     cpi    'I'-040h    ; check for a tab
  195.     rz            ; return if we have one
  196.     cpi    'J'-040h    ; check for a newline
  197.     rz            ; return if we have one
  198.     dcr    l        ; make the result FALSE
  199.     ret            ; return to caller
  200.  
  201.     ENDFUNC isspace
  202.     page
  203. ;
  204. ;    Function:    atoi()
  205. ;
  206. ;
  207. ;    This function converts an ascii integer to its binary equivalent. White
  208. ;    space at the front of the string is ignored, and a minus sign is
  209. ;    recognized.
  210. ;
  211. ;    int    atoi(str)
  212. ;    char    *str;
  213. ;
  214.  
  215.     FUNCTION    atoi
  216.  
  217.     pop    h        ; fetch the return address
  218.     pop    d        ; fetch the pointer to the string
  219.     push    d        ; put everything back the way it was
  220.     push    h
  221.     push    b        ; save the BC register
  222.     lxi    h,0        ; zero the number accumulator
  223.     xra    a        ; set the sign flag to POSITIVE
  224.     push    psw        ; save the sign flag on the stack
  225.  
  226. atoi10:    ldax    d        ; fetch the next byte of the string
  227.     inx    d        ; increment the string pointer
  228.     cpi    ' '        ; check for a leading space
  229.     jz    atoi10        ; go skip the space
  230.     cpi    'I'-040h    ; check for a leading tab
  231.     jz    atoi10        ; go skip the tab
  232.     cpi    '-'        ; check for the minus sign
  233.     jnz    atoi20        ; jump if no minus sign
  234.     pop    psw        ; fetch the sign flag
  235.     inr    a        ; change the flag to NEGATIVE
  236.     push    psw        ; put the sign flag back
  237.     ldax    d        ; fetch the next string character
  238.     inx    d        ; increment the pointer
  239.  
  240. atoi20:    sui    '0'        ; convert the alleged digit to binary
  241.     cpi    10        ; it can't be larger than 9
  242.     jnc    atoi30        ; jump if this isn't an ascii digit
  243.     mov    b,h        ; copy the accumulator into BC
  244.     mov    c,l
  245.     dad    h        ; multiply the accumulator by 8
  246.     dad    h
  247.     dad    h
  248.     dad    b        ; adding the original accumulator in twice...
  249.     dad    b        ;   multiplies the accumulator by 10.
  250.     mov    c,a        ; put the current digit into BC
  251.     mvi    b,0
  252.     dad    b        ; add in the current digit
  253.     ldax    d        ; fetch the next string character
  254.     inx    d        ; increment the string pointer
  255.     jmp    atoi20        ; go check for another digit
  256.  
  257. atoi30:    pop    a        ; end of number - fetch the sign flag
  258.     pop    b        ; restore the BC register
  259.     rz            ; return if the sign flag is POSITIVE
  260.     mov    a,h        ; two's complement the accumulator
  261.     cma
  262.     mov    h,a
  263.     mov    a,l
  264.     cma
  265.     mov    l,a
  266.     inx    h
  267.     ret            ; return to caller
  268.  
  269.     ENDFUNC atoi
  270.     page
  271. ;
  272. ;    Function:    strlen()
  273. ;
  274. ;
  275. ;    This function returns the length in bytes of its string argument.  The
  276. ;    terminating zero byte is not counted in the length.
  277. ;
  278. ;    unsigned strlen(str)
  279. ;    char    *str;
  280. ;
  281.  
  282.     FUNCTION    strlen
  283.  
  284.     pop    h        ; fetch the return address...
  285.     pop    d        ; fetch the string pointer
  286.     push    d        ; put everything back the way it was
  287.     push    h
  288.     mov    h,d        ; copy the string pointer into HL
  289.     mov    l,e
  290.  
  291. slen10:    ldax    d        ; fetch the next byte of the string
  292.     inx    d        ; increment the string pointer
  293.     ora    a        ; check for a zero byte
  294.     jnz    slen10        ; loop until we reach the end of the string
  295.  
  296. ;
  297. ;    To compute the length, we subtract the original string pointer from
  298. ;    the new string pointer (which is pointing to the zero byte at the
  299. ;    end of the string).
  300. ;
  301.  
  302.     dcx    d        ; we don't want to count the zero byte
  303.     mov    a,e        ; subtract the low order bytes first
  304.     sub    l
  305.     mov    l,a
  306.     mov    a,d        ; subtract the high order bytes next
  307.     sbb    h
  308.     mov    h,a
  309.     ret            ; return to caller with the string length
  310.  
  311.     ENDFUNC strlen
  312.     page
  313. ;
  314. ;    Function:    strcmp()
  315. ;
  316. ;
  317. ;    This function compares two strings.  If the first argument is either
  318. ;    longer than the second argument, or one if its bytes is arithmetically
  319. ;    greater than the corresponding byte of the second argument (using the
  320. ;    ASCII collating sequence), then a positive number is returned.  If the
  321. ;    second argument is greater than the first, a negative number is
  322. ;    returned.  If the strings are equal, zero is returned.
  323. ;
  324. ;    If a positive or negative number is returned, the actual value returned
  325. ;    is meaningless.  Only the sign is of use.
  326. ;
  327. ;    int    strcmp(s1, s2)
  328. ;    char    *s1, *s2;
  329. ;
  330.  
  331.     FUNCTION    strcmp
  332.  
  333.     call    arghak        ; hack apart the arguments
  334.     lhld    arg1        ; fetch the string 1 pointer
  335.     xchg            ; put it into DE
  336.     lhld    arg2        ; fetch the string 2 pointer
  337.  
  338. scmp10:    ldax    d        ; fetch the next byte of string 1
  339.     cmp    m        ; compare with the next byte of string 2
  340.     jnz    scmp20        ; jump if the bytes are not equal
  341.     inx    h        ; increment the string pointers
  342.     inx    d
  343.     ora    a        ; if the byte is zero, we're all done
  344.     jnz    scmp10        ; loop if we're not done yet
  345.     lxi    h,0        ; return zero - the strings are equal
  346.     ret            ; return to caller
  347.  
  348. scmp20:    sub    m        ; figure out which byte (and string) is larger
  349.     mov    h,a        ; return the result in HL
  350.     ret            ; return to caller
  351.  
  352.     ENDFUNC strcmp
  353.     page
  354. ;
  355. ;    Function:    strcpy()
  356. ;
  357. ;
  358. ;    This function copies the source string onto the destination string.  If
  359. ;    the destination string should happen to be valid, it will be destroyed.
  360. ;    There MUST be enough room allocated for the destination string to hold
  361. ;    the entire source string, or the code or data following the destination
  362. ;    string will be overwritten.
  363. ;
  364. ;    The function returns a pointer to the destination string.
  365. ;
  366. ;    char    *strcpy(dest, source)
  367. ;    char    *dest, *source;
  368. ;
  369.  
  370.     FUNCTION    strcpy
  371.  
  372.     call    arghak        ; go hack apart the arguments
  373.     lhld    arg1        ; fetch the destination string pointer
  374.     xchg            ; put the pointer into DE
  375.     lhld    arg2        ; fetch the source string pointer
  376.  
  377. scpy10:    mov    a,m        ; fetch the next byte of the source string
  378.     stax    d        ; store the byte into the destination string
  379.     inx    d        ; increment the string pointers
  380.     inx    h
  381.     ora    a        ; if A is zero, we've reached the string end
  382.     jnz    scpy10        ; loop if we're not at the end
  383.     lhld    arg1        ; return a pointer to the destination string
  384.     ret            ; return to caller
  385.  
  386.     ENDFUNC strcpy
  387.     page
  388. ;
  389. ;    Function:    strcat()
  390. ;
  391. ;
  392. ;    This function concatenates the source string onto the destination
  393. ;    string.  There MUST be enough room allocated at the end of the
  394. ;    destination string to hold the entire source string.
  395. ;
  396. ;    char    *strcat(dest, source)
  397. ;    char    *dest, *source;
  398. ;
  399.  
  400.     FUNCTION    strcat
  401.  
  402.     call    arghak        ; go hack apart the arguments
  403.     lhld    arg2        ; fetch the source string pointer
  404.     xchg            ; put the pointer into DE
  405.     lhld    arg1        ; fetch the destination string pointer
  406.  
  407. ;
  408. ;    The loop below finds the end of the destination string.
  409. ;
  410.  
  411. scat10:    mov    a,m        ; fetch the next byte of the destination string
  412.     inx    h        ; increment the string pointer
  413.     ora    a        ; if A is non-zero, we need to keep searching
  414.     jnz    scat10        ; loop until we reach the end of the string
  415.     dcx    h        ; point back to the zero terminating byte
  416.  
  417. ;
  418. ;    Now we copy the source onto the end of the destination.
  419. ;
  420.  
  421. scat20:    ldax    d        ; fetch the next source string byte
  422.     mov    m,a        ; store the byte into the destination string
  423.     inx    h        ; increment the string pointers
  424.     inx    d
  425.     ora    a        ; if A is zero, we've reached the end
  426.     jnz    scat20        ; loop if we have more to do
  427.     lhld    arg1        ; return a pointer to the destination string
  428.     ret            ; return to caller
  429.  
  430.     ENDFUNC strcat
  431.  
  432.     page
  433. ;
  434. ;    Function:    move()
  435. ;
  436. ;
  437. ;    This function moves <length> bytes from location <source> to
  438. ;    location <destination>. The move is performed from first to
  439. ;    last bytes so if there is overlap of range, be sure that
  440. ;    <source> greater than <destination>. If this condition is not
  441. ;    true use the 'movdn' function instead.  The block move 
  442. ;    instruction is used if the Z80 equate is true.
  443. ;
  444. ;    move(dest, source,length)
  445. ;    char    *dest, *source;
  446. ;    int    length
  447.  
  448.     FUNCTION    move
  449.  
  450.     call    arghak        ; go hack apart the arguments
  451.     lhld    arg1        ; fetch the destination pointer
  452.     xchg            ; put the pointer into DE
  453.     lhld    arg3        ; fetch the length
  454.     mov    a,h
  455.     ora    l        ; return on zero
  456.     rz
  457.     push    h
  458.     pop    b        ; put into BC
  459.     lhld    arg2        ; fetch the source pointer
  460. mve10:
  461.     if    z80
  462.  
  463.     db    0edh,0b0h    ; perform LDIR instruction
  464.     ret            ; return to caller
  465.  
  466.     else    ; 8080
  467.  
  468.     mov    a,m        ; fetch the next byte of the source string
  469.     stax    d        ; store the byte into the destination string
  470.     inx    d        ; increment the string pointers
  471.     inx    h
  472.     dcx    b        ; decrement count
  473.     mov    a,b        ; test zero in b
  474.     ora    c        ; and c
  475.     
  476.     endif
  477.  
  478.     jnz    mve10        ; loop if we're not at the end
  479.     ret            ; return to caller
  480.  
  481.     ENDFUNC move
  482.  
  483.     FUNCTION    movdn
  484.     page
  485. ;
  486. ;    Function:    movdn()
  487. ;
  488. ;
  489. ;    This function moves <length> bytes from location <source> to
  490. ;    location <destination>. The move is performed from last to
  491. ;    first bytes so if there is overlap of range, be sure that
  492. ;    <source> less than <destination>. If this condition is not
  493. ;    true use the 'move' function instead.  Also use 'move' if
  494. ;    there is no overlap since it is more efficient. The block move 
  495. ;    instruction is used if the Z80 equate is true.
  496. ;
  497. ;    movdn(dest, source , length)
  498. ;    char    *dest, *source;
  499. ;    int    length
  500.  
  501.     call    arghak        ; go hack apart the arguments
  502.     lhld    arg3        ; fetch the length
  503.     mov    a,h
  504.     ora    l        ; return on zero
  505.     rz
  506.     push    h        ; save
  507.     xchg            ; into DE
  508.     lhld    arg1        ; fetch the destination pointer
  509.     dad    d        ; add length
  510.     dcx    h        ; one too many
  511.     push    h
  512.     lhld    arg3        ; fetch the length
  513.     xchg            ; into DE
  514.     lhld    arg2        ; fetch the source pointer
  515.     dad    d        ; add length
  516.     dcx    h        ; one too many
  517.     pop    d        ; get back destination
  518.     pop    b        ; and length
  519.  
  520. mvdn10:
  521.     if    z80
  522.  
  523.     db    0edh,0b8h    ; perform LDDR instruction
  524.     ret            ; return to caller
  525.  
  526.     else    ; 8080
  527.  
  528.     mov    a,m        ; fetch the next byte of the source string
  529.     stax    d        ; store the byte into the destination string
  530.     dcx    d        ; increment the string pointers
  531.     dcx    h
  532.     dcx    b        ; decrement count
  533.     mov    a,b        ; test zero in b
  534.     ora    c        ; and c
  535.     
  536.     endif
  537.  
  538.     jnz    mvdn10        ; loop if we're not at the end
  539.     ret            ; return to caller
  540.  
  541.     ENDFUNC movdn
  542.  
  543.     end
  544.