Search code examples
x86-16tasm

TASM 8086 Trying Count the characters of a string and display them in a table


Please forgive some of the spacing in the program, the editor I am using displays tabs with a different spacing than how they are displayed here

Currently attempting to count the characters of a user-input string. I have thoroughly searched for help over the internet, but it seems that there is not that much current help when it comes to coding in 8086. Here is what I have so far:

    .MODEL  small
    STACK   256

;************************************************************************
;* Equates Section                                                                  *
;************************************************************************

EOS     EQU 0       ;End of string
maxLen  EQU 255     ;Maximum entry string length
bell      EQU   7       ;Bell character -- <ctrl>G

;************************************************************************
;* Data Section                                                                       *
;************************************************************************
  .DATA
excode  db  0     ;DOS error code
enter1  db  'Enter a string: ',EOS          ;Prompt user for input
enter2  db  'Would you like to count another string?',EOS
                                            ;Prompt user for another string
buffer  db maxLen dup (?)                   ;input/output buffer
buffer1 db maxLen dup (?)                   ;input/output buffer

spaces  db  '   ',EOS                       ;Used for spacing
letter  db  'Letter ',EOS                   ;String used for first column
freq    db  'Frequency',EOS                 ;String used for second column
cBord1  db  '------ ',EOS                   ;String used to mark column border
cBord2  db  '---------', EOS                ;String used to makr column border

currLet dw  0
strLet  dw  0
side    db  0                               ;0=Left side, 1=Right side

count   db  0


exitProg db 'Exiting program',EOS           ;Exit message

;************************************************************************
;* Code Section                                                                       *
;************************************************************************
  .CODE

;************************************************************************
;* External procedures from BINASC.OBJ                                                                  *
;************************************************************************
    EXTRN AscToBin:proc, binToAscDec:proc
;************************************************************************
;* External proceduers from STRING.OBJ & STRIO.OBJ                      *
;************************************************************************
  EXTRN StrLength:proc, StrRead:proc
  EXTRN StrWrite:proc, Newline:proc


;************************************************************************
;* Main entry point of program                                          *
;************************************************************************
Start:
  mov ax, @data     ;Initialize DS to address
  mov ds, ax        ;  of data segment
  mov es, ax        ;make es = ds
;************************************************************************
;* Get user input and conver to uppercase                               *
;************************************************************************
First:
    call  Newline     ;Start new display line
    lea   di, enter1  ;Display message to enter a string
    call  StrWrite
    mov     si, 0

    lea   di, buffer    ;Get user input
    mov   cx, maxLen    ;Maximum string length
    call  StrRead           ;Get entry from keyboard
    lea   si, buffer  ;Move string into si

Back:
    mov   al, [si]    ;Move si location to al
    cmp   al, 'a'     ;Compare al to 'a'
    jb    Ahead       ;Jump if less than
    cmp   al, 'z'     ;Compare al to 'z'
    ja    Ahead       ;Jump if greater than

    and   al, 0DFh    ;Convert letter to uppercase
    mov   [si], al


Ahead:
    inc si          ;increment value of si
    loop Back       ;loop back to

;Display table head
    call Newline
    lea  di, buffer
    call StrWrite

    call Newline
    lea  di, letter
    call StrWrite
    lea  di, freq
    call StrWrite
    lea  di, spaces
    call StrWrite
    lea  di, letter
    call StrWrite
    lea  di, freq
    call StrWrite

    call Newline
    lea  di, cBord1
    call StrWrite
    lea  di, cBord2
    call StrWrite
    lea  di, spaces
    call StrWrite
    lea  di, cBord1
    call StrWrite
    lea  di, cBord2
    call StrWrite

    call Newline

    mov  si, 0        ;clear si

ploop:
    mov  ax, si       ;set ax register equal to si
    add  al, 'A'      ;Move 'A' into low bit of ax
    mov  currLet, ax  ;Move ax reigster into currLet

    mov  side, 0      ;set side to Left

sloop:
    mov  buffer1, al      ;Move current letter into buffer1
    mov  buffer1+1, EOS   ;clear end of buffer1
    lea  di, buffer1      ;Move letter into di
    call StrWrite         ;Write letter to screen

;Separate letters from their counts
    lea  di, spaces
    call StrWrite
    call StrWrite

    mov  count, 0      ;clear count
    mov cx, 0          ;clear cx register
    mov cx, maxLen     ;set cx to maxLen

    CntBack:
      lea  di, buffer      ;Move input string into di
      mov  bl, [di]        ;Move di location to bl
      mov  strLet, bx      ;Move current letter of string
      jmp CntFwrd
    CntUp:
       inc count
       inc di
       loop CntBack
    CntFwrd:
      mov  ax, strLet
      cmp  ax, currLet ;compare string letter and current letter
      je   CntUp
      inc  di
      loop CntBack

    mov  ax, 0
    mov  cx, 3
    mov  al, count
    lea  di, count
    call binToAscDec
    call StrWrite

    cmp  side, 1
    je   nextRow
    inc  side

    ;right side
    lea  di, spaces
    call StrWrite
    call StrWrite
    call StrWrite

    add  currlet, 13
    mov  ax, currlet
    jmp  sloop

nextRow:
    call Newline
    inc  si
    cmp  si, 13
    je   Exit
    jmp  ploop

;************************************************************************
;* Exit program                                                                     *
;************************************************************************
Exit:
    call    Newline
    call  Newline
    lea   di, exitProg      ;Call exit program message
    call  StrWrite
;************************************************************************
;* Program termination code                                                     *
;************************************************************************
    mov ah, 04Ch        ;DOS function Exit Program
    mov al, excode  ;Return exit code value
    int 21h             ;Call DOS. Terminate program
    END Start           ;  End of program/entry point

I believe that my problem is in this snippet of the code:

    CntBack:
      lea  di, buffer      ;Move input string into di
      mov  bl, [di]        ;Move di location to bl
      mov  strLet, bx      ;Move current letter of string
      jmp CntFwrd
    CntUp:
       inc count
       inc di
       loop CntBack
    CntFwrd:
      mov  ax, strLet
      cmp  ax, currLet ;compare string letter and current letter
      je   CntUp
      inc  di
      loop CntBack

If I were to enter the string 'hello' the program should display this:

Letter Frequency   Letter Frequency
------ ---------   ------ ---------
A      000         N      000
B      000         O      001
C      000         P      000
D      000         Q      000
E      001         R      000
F      000         S      000
G      000         T      000
H      001         U      000
I      000         V      000
J      000         W      000
K      000         X      000
L      002         Y      000
M      000         Z      000

But I will instead receive something like this in the display:

Letter Frequency   Letter Frequency
------ ---------   ------ ---------
A      000         N      000
B      000         O      000
C      000         P      000
D      000         Q      000
E      000         R      000
F      000         S      000
G      000         T      000
H      _

It seems that the code is not counting the entire input string, and instead is only comparing the first strLet, which is the first letter of the string, with the currlet value


Solution

  • At the top of the CntBack loop, you're setting DI to point to the start of the input buffer. After you compare the first character and increment DI, you loop back to CntBack which resets DI to point to the same first character of the input buffer.

    So, you're just comparing against the first character of your string over and over until your CX count is exhausted. Try moving the CntBack label down one instruction, and see if that fixes the problem.