S100 Computers

HomeS-100 Boards HistoryNew BoardsSoftwareBoards For Sale
ForumOther Web SitesQuizIndex   
  
Under Construction
A Collection of Useful Assembly Language Routines
Here is a growing collection of small but useful Z80, 8080 and 8086 Assembly Language routines I use time and time again in programs.  Other donations will be gratefully received.

  ; BDOS EQUATES for running these routines under CPM
;
RDCON       EQU   1     ;CP/M Read character
WRCON       EQU   2     ;CP/M Write character
PRINT       EQU   9     ;CP/M Print string
BDOS        EQU   5
ESC         EQU   1BH
CR          EQU   0DH
LF          EQU   0AH
 
; Main consol output routine using CPM.
; Character to be sent in [C].
; All registers unchanged
 
ZCO:  PUSH  AF
      PUSH  BC
      PUSH  DE
      LD    E,C
      LD    C,WRCON
      CALL  BDOS
      POP   DE
      POP   BC
      POP   AF
      RET
To Download Text Click Here

 
; Main consol input routine using CPM.
; Character returned in [A].
; All registers (except [A]) unchanged
 
ZCI:  PUSH  BC
      PUSH  DE
      LD    C,RDCON
      CALL  BDOS
      POP   DE
      POP   BC
      RET
To Download Text Click Here

 
; DISPLAY BIT PATTERN IN [A]  (ZILOG)
; All registers unchanged
; The output will look like:- (10100110)
 
ZBITS:PUSH  AF
      PUSH  BC
      PUSH  DE
      PUSH  AF
      LD    C,' '
      CALL  ZCO
      LD    C,'('
      CALL  ZCO
      POP   AF
      LD    E,A        
      LD    B,8
BQ2:  SLA   E    
      LD    A,18H
      ADC   A,A
      LD    C,A
      CALL  ZCO
      DJNZ  BQ2
      LD    C,')'
      CALL  ZCO
      POP   DE
      POP   BC
      POP   AF
      RET
To Download Text Click  Here

; Return with 2 HEX digits in [A] from keyboard
; If abort, Carry flag set & ESC is returned in [A]
; All registers unchanged except [A]    (INTEL)
 
GETHEX:
      PUSH  B
      MVI   C,RDCON
      CALL  BDOS        ;Get a character from keyboard & ECHO          
      CPI   ESC
      JZ    HEXABORT
      CPI   '/'         ;check 0-9, A-F
      JC    HEXABORT
      CPI   '9'+1
      JNC   HEXABORT
      CALL  ASBIN       ;Convert to binary
      RLC               ;Shift to high nibble
      RLC
      RLC
      RLC
      MOV   B,A         ;Store it
      PUSH  B
      MOV   C,RDCON
      CALL  BDOS        ;Get 2nd character from keyboard & ECHO
      POP   B          
      CPI   ESC
      JZ    HEXABORT
      CPI   '/'         ;check 0-9, A-F
      JC    HEXABORT
      CPI   '9'+1
      JNC   HEXABORT
      CALL  ASBIN       ;Convert to binary
      ORA   B           ;add in the first digit
      ORA   A           ;To return NC
      POP   B
      RET
;
HEXABORT:
      STC               ;Set Carry flag
      MVI   A,ESC
      POP   B
      RET
;                       ;Convert LC to UC
UPPER:CPI   'a'         ;must be >= lowercase a
      RC                ; else go back...
      CPI   'z'+1       ;must be <= lowercase z
      RNC               ; else go back...
      SUI   'a'-'A'           ;subtract lowercase bias
      RET
;                      
ASBIN:SUI   30H          ;ASCII TO BINARY CONVERSION ROUTINE
      CPI   0AH
      RM
      SUI   07H
      RET
 
 
To Download Text Click  Here

 
; DISPLAY CURRNT VALUE IN [A] (ZILOG)
; All registers unchanged
 
LBYTE:PUSH  AF
      PUSH  BC
      PUSH  AF
      RRCA
      RRCA
      RRCA
      RRCA
      CALL  CONV
      CALL  ZCO 
      POP   AF
SF598:CALL  CONV
      CALL  ZCO   ;Send to consol
      POP   BC
      POP   AF
      RET
;
CONV: AND   0FH   ;CONVERT HEX TO ASCII
      ADD   A,90H
      DAA
      ADC   A,40H
      DAA
      LD    C,A
      RET
To Download Text Click  Here

 
; DISPLAY CURRNT VALUE IN [A] (INTEL)
; All registers unchanged
 
LBYTE:PUSH  PSW  
      PUSH  B
      PUSH  PSW
      RRC
      RRC
      RRC
      RRC
      CALL  ZCONV
      POP   PSW
      CALL  ZCONV
      MVI   C,' '
      CALL  ZCO
      POP   B
      POP   PSW
      RET
;
ZCONV:ANI   0FH   ;HEX to ASCII and print it
      ADI   90H
      DAA
      ACI   40H
      DAA
      MOV   C,A
      CALL  ZCO
      RET
To Download Text Click  Here

 
; Return with 2 HEX digits in [A] from keyboard
; If abort, Carry flag set & ESC is returned in [A]
; All registers unchanged except [A]    (ZILOG)
 
GETHEX:
      PUSH  BC
      LD    C,RDCON                
      CALL  BDOS        ;Get a character from keyboard & ECHO
      CALL  UPPER
      CP    A,ESC
      JR    Z,HEXABORT
      CP    '/'         ;check 0-9, A-F
      JR    C,HEXABORT
      CP    'F'+1
      JR    NC,HEXABORT
      CALL  ASBIN       ;Convert to binary
      SLA   A
      SLA   A
      SLA   A
      SLA   A           ;Shift to high nibble  
      LD    B,A         ;Store it
      PUSH  BC          ;Because CP/M destroys BC
      LD    C,RDCON                
      CALL  BDOS        ;Get a character from keyboard & ECHO
      POP   BC
      CALL  UPPER
      CP    A,ESC
      JR    Z,HEXABORT
      CP    '/'         ;check 0-9, A-F
      JR    C,HEXABORT
      CP    'F'+1
      JR    NC,HEXABORT
      CALL  ASBIN       ;Convert to binary
      OR    A,B         ;add in the first digit
      OR    A,A         ;To return NC
      POP   BC
      RET
;
HEXABORT:
      SCF               ;Set Carry flag
      LD    A,ESC
      POP   BC
      RET
;
ASBIN:SUB   30H   ; ASCII TO BINARY CONVERSION ROUTINE
      CP    0AH
      RET   M
      SUB   07H
      RET
;
UPPER:CP    A,'a'
      RET   C
      CP    A,'z'+1
      RET   NC
      SUB   A,'a'-'A'
      RET
To Download Text Click  Here


; Binary to ASCII Decimal String Conversion Print Routine
; [DE] contains binary number to be displayed as a decimal number.
; Note String is built right->left in buffer
; Then printed out via CPM.         (ZILOG)
;
PRINT_DEC:
      LD    HL,BUFFER   ;Location to hold string
      LD    (BUFPTR),HL ;Save buffer pointer
      EX    DE,HL
      LD    A,0
      LD    (CURLEN),A  ;Current length of buffer is 0
      LD    A,H
      LD    (NGFLAG),A  ;Save Sign Value
      OR    A           ;Set FLAGS Value
      JP    P,CNVERT    ;JMP IF VALYE IS +
      EX    DE,HL
      LD    HL,0
      OR    A           ;CLEAR Carry
      SBC   HL,DE
                        ;Convert Value to a String
CNVERT:    
      LD    E,0         ;HL := HL DIV 10,  DE := HL MOD 10
      LD    B,16
      OR    A
DVLOOP:    
      RL    L           ;Do a 24-bit shift left
      RL    H
      RL    E
      LD    A,E
      SUB   10          ;If remainder is 10 or more next 1
      CCF
      JR    NC,DECCNT
      LD    E,A
DECCNT:    
      DJNZ  DVLOOP       ;continue until all bits are done
      RL    L
      RL    H
CHINS:LD    A,E         ;Insert next character into buffer
      ADD   A,'0'
      CALL  INSERT
      LD    A,H
      OR    L
      JR    NZ,CNVERT
     
EXIT: LD    A,(NGFLAG)  ;All done
      OR             ;Check it + or - overall
      JP    P,POS
      LD    A,'-'
      CALL  INSERT
POS:  LD    HL,BUFFER
      LD    A,(HL)      ;number of characters in buffer
      INC   A
      LD    C,A
      LD    B,0
      ADD   HL,BC       ;Point to end of buffer
      LD    (HL),'$'    ;Put in terminating character for CPM
      LD    DE,BUFFER+1 ;Now print the complete string
      LD    C,PRINT     ;(+1, because buffer count is in first posttion)
      CALL  BDOS
      RET
 
INSERT:     PUSH  HL     ;Save for now
      PUSH  AF
      LD    HL,(BUFPTR) ;Current end of buffer
      LD    D,H
      LD    E,L
      INC   DE          ;DE = End+1
      LD    (BUFPTR),DE
      LD    A,(CURLEN)
      OR    A
      JR    Z,EXITMR
      LD    C,A
      LD    B,0
      LDDR              ;Move entire buffer up one byte
EXITMR:    
      LD    A,(CURLEN)
      INC   A
      LD    (CURLEN),A
      LD    (HL),A
      EX    DE,HL
      POP   AF
      LD    (HL),A
      POP   HL
      RET
 
BUFPTR:     DS    2           ;pointer to last character in buffer
CURLEN:     DS    1           ;Current length
NGFLAG:     DS    1
BUFFER:     DB    '           $'    ;<<<<< Decimal string will be built here
To download Text Click  Here


 
; Do a hexdump of the data in that is in a 512 byte (typically a BIOS DMA) buffer
; [HL] points to the buffer. Change values for [DE] below for different size buffers
; No registers modified    (INTEL)
 
 
HEXDUMP:
      PUSH  PSW         ;Save everything
      PUSH  D
      PUSH  H
      CALL  CRLF        ;CR/LF first
 
      MVI   D,32        ;print 32 lines
      MVI   E,16        ;16 characters across
      PUSH  D
      PUSH  H           ;Save the buffer location
;
SF172:CALL  ZCRLF
SF175:CALL  BLANK
      MOV   A,M
      CALL  LBYTE       ;Display A on CRT/LCD
      INX   H
      DCR   E
      JNZ   SF175
      MVI   E,16
      DCR   D
      JNZ   SF172
;
      CALL  ZCRLF
      POP   H           ;Get buffer address again
      POP   D           ;Get chars/line again
;
XF172:CALL  ZCRLF       ;Now show as ascii
XF175:CALL  BLANK       ;send a space character
      MOV   A,M
      ANI   7FH
      CPI   ' '         ;FILTER OUT CONTROL CHARACTERS
      JNC   XT33
XT22: MVI   A,'.'
XT33: CPI   07CH
      JNC   XT22
      MOV   C,A         ;SET UP TO SEND
      CALL  ZCO
      INX   H
      DCR   E
      JNZ   XF175
      MVI   E,16
      DCR   D
      JNZ   XF172
      CALL  ZCRLF
       POP   H
       POP   D
       POP   B
      POP   PSW
      RET
;
BLANK:MVI   C,' '
      CALL  ZCO
      RET
;
ZCRLF:MVI   C,CR
      CALL  ZCO
      MVI   C,LF
      CALL  ZCO
      RET
To Download Text Click Here

 
   
;Convert BCD number (Two digits only) in A to Binary
;No registers modified    (INTEL)
  
BCDTOBIN:
       PUSH B
       PUSH D
       MOV B,A   ;Save it
       ANI 0FH   ;Mask most significant four bits
       MOV C,A   ;Save unpacked BCDI in C register
       MOV A,B   ;Get BCD again
       ANI 0F0H  ;Mask least significant four bits
       RRC       ;Convert most significant four bits into unpacked BCD2
       RRC
       RRC
       RRC
       MOV B,A   ;Save unpacked BCD2 in B register
       XRA A     ;Clear accumulator (sum = 0)
       MVI D,0AH ;Set D as a multiplier of 10
Sum:   ADD D     ;Add 10 until (B) = 0
       DCR B     ;Decrement BCD2 by one
       JNZ Sum   ;Is multiplication complete? i if not, go back and add again
       ADD C     ;Add BCD1
       POP D
       POP B
       RET       ;Return with binary value in [A]

 
To Download Text Click Here
  


 
;Generalized Subroutine to convert binary number in [A] into its equivalent BCD number ;stored in RAM. Will return right most 2 digits in [A]
;No registers modified (INTEL)

BINTOBCD:          ;Convert binary number in [A] to BCD in RAM
        PUSH B     ;Save BC register pair contents
        PUSH D     ;Save DE register pair contents
        MVI B,64H  ;Load divisor decimal 100 in B register
        MVI C,0AH  ;Load divisor decimal 10 in C register
        MVI D,00H  ;Initialize Digit 1
        MVI E,00H  ;Initialize Digit 2
STEP1:  CMP B      ;Check if number < Decimal 100
        JC STEP2   ;if yes go to step 2
        SUB B      ;Subtract decimal 100
        INR E      ;update quotient
        JMP STEP1  ;go to step 1
STEP2:  CMP C      ;Check if number < Decimal 10
        JC STEP3   ;if yes go to step 3
        SUB C      ;Subtract decimal 10
        INR D      ;Update quotient
        JMP STEP2  ;Continue division by 10
STEP3:  STA Digit0 ;Store Digit 0
        MOV A,D    ;Get Digit 1
        STA Digit1 ;Store Digit 1
        RLC        ;Shift it up 4 bits
        RLC
        RLC
        RLC
        ANI 0F0H
        MOV D,A    ;Temp store in D
        MOV A,E    ;Get Digit 2
        STA Digit2 ;Store Digit 2
        LDA Digit0
        ORA D      ;Add in 10's digit
        POP D      ;Restore DE register pair
        POP B      ;Restore BC register pair
        RET        ;Return to main program


Digit0: DB 0       ;Store for Bin->BCD
Digit1: DB 0
Digit2: DB 0
To Download Text Click Here
  

This page was last modified on 12/24/2011