S100 Computers

HomeS-100 Boards HistoryNew BoardsSoftwareBoards For Sale
ForumOther Web SitesNewsIndex  
  

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, Z80)
; 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

 
; DISPLAY BIT PATTERN IN [A]  (Intel, 8080)
; All registers unchanged
; The output will look like:- (10100110)
 
ZBITS:PUSH  PSW
      PUSH  B
      PUSH  D
       PUSH  PSW
      MVI   C,' '
      CALL  ZCO
      MVI   C,'('
      CALL  ZCO
       POP   PSW
      LD    E,A        
      LD    B,8
BITS2:MOV   A,E     ;There is no 8080 equivalent to the Z80's SLA E
      ANI   80H
      JZ    BITS4
      MVI   C,'1'
BITS3:CALL  CO
      MOV   A,E
      RAL
      MOV   E,A
      DCR   B
      JNZ   BITS2
      JMP   BQ2
BITS4:MVI   C,'0'
      JMP   BITS3

BQ2:  LD    C,')'
      CALL  ZCO
      POP   DE
      POP   BC
      POP   AF
      RET
To Download Text Click  Here

; Obtain 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


 
; 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 05/14/2016