Search code examples
assemblypalindromeemu8086

Palindrome program for emu8086 in assembly language


I'm trying to complete my last lab exercise for my microprocessors course and could really use some help with this. The job is to fill the commented empty lines with my own code. Here's the task:

**Task 2. Test if the string is a palindrome** 
Modify the previous program so, that it checks whether the string is a palindrome. Complement the following program. Add the missing instructions.

    include "emu8086.inc"
; START-OF-PROGRAM
    org 100h
        jmp start  

; Memory variables:
msg3        db      0ah,0dh,"The string is a palindrome.",0
msg2    db  0ah,0dh,"The string is NOT a palindrome.",0 
msg1    db  "Enter a string (max 128 characters): ",0
; the buffer to save the entered string    
mystr   db      128 dup (0),0
mystrREV    db      128 dup (0),0
endl    db      0dh,0ah,0
length  db  0

start:      lea     SI, msg1    ; Message address
        CALL    PRINT_STRING    ; Print message from [SI]
            ; String mystring: Read string here!
            ; String max. length
            ; Read string into [DI]
    lea     si,endl
    call    print_string


; count the number of characters in the buffer mystr into CX:
    mov cl,0    ; start from 0
    lea SI,mystr    ; Point SI to mystr
tess:   mov al,[SI],0   ; End of data?
    cmp al,0    ; -“-
    je  seur    ; Proceed to next step
    inc cl  ; Increment data counter
    inc SI  ; Increment data pointer
    jmp tess    ; Check next
; copy mystr into mystrREV in reverse order
seur:   mov length,cl   ; Store # of characters in length
            ; Result buffer address into DI
            ; Source buffer address id SI(decremented)
coop:           ; Copy character from source
            ; Copy character to destination
            ; Decrement source pointer
            ; Increment result pointer
            ; Decrement counter
            ; Take next if not done

; print both buffers
    lea     si,mystr
    call    print_string    ; Print mystr
    lea     si,endl
    call    print_string    ; Print cr+lf

    lea     si,mystrREV
    call    print_string    ; Print mystrREV
    lea     si,endl
    call    print_string    ;print cr+lf

; compare strings. If equal => palindrome
    mov cl,length   ; # of characters in buffers 
    lea     si,mystr    ; address of first buffer
    lea di,mystrREV ; address of second buffer
niis:   cmp cl,0    ; test if end-of-comparison/buffer
            ; jump to ok, palindrome/empty buffer   
            ; Source buffer address
            ; Result buffer address
            ; Are same, still chance?
            ; Nop, jump to print NOT-message and exit
            : increment source pointer
            ; increment destination pointer
            ; decrement counter
    jmp     niis    ; Try next

positive: lea   SI,msg3 ; Yess, palindrome
    call    PRINT_STRING    ; Print it
    jmp bort    ; and exit

negative: lea   si,msg2 ; NOT a palindrome
    call    PRINT_STRING    ; Print it and exit

bort:   mov ax,4c00h    ; code for return to ms-dos
    int 21h ; call ms-dos terminate program
    ret

; Macro definitions
DEFINE_GET_STRING
DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
    end                     ;END-OF-PROGRAM

My program only prints the first letter of the input string as reversed string and doesn't really test the palindrome properly. This is what I've done so far:

            include "emu8086.inc"
; START-OF-PROGRAM
            org 100h
            jmp start  

; Memory variables:
msg3        db    0ah,0dh,"The string is a palindrome.",0
msg2        db    0ah,0dh,"The string is NOT a palindrome.",0 
msg1        db    "Enter a string (max 128 characters): ",0
; The buffer to save the entered string    
mystr       db    128 dup (0),0
mystrREV    db    128 dup (0),0
endl        db    0dh,0ah,0
length      db    0

start:  lea     SI, msg1        ; Message msg1 address
        CALL    PRINT_STRING    ; Print message from [SI] 

; *********************** My code starts *********************

    lea di, mystr           ; String mystring: Read string here!
    mov dx, 128             ; String max. length
    call get_string         ; Read string into [DI]            

; *********************** My code ends ***********************  

    lea     si,endl         ; String endl
    call    print_string    ; Print endl
; count the number of characters in the buffer mystr into CX:
    mov     cl,0            ; start from 0
    lea     SI,mystr        ; Point SI to mystr
tess:   mov al,[SI],0       ; End of data?
    cmp     al,0            ; -"-
    je      seur            ; Proceed to next step
    inc     cl              ; Increment data counter
    inc     SI              ; Increment data pointer
    jmp     tess            ; Check next
; copy mystr into mystrREV in reverse order
seur:   mov length,cl       ; Store # of characters in length

; *********************** My code starts *********************  

; Something goes wrong in this code block   
    lea di, mystrREV        ; Result buffer address into DI
    lea si, mystr       ; Source buffer address id SI(decremented)
coop:mov al, [si]   ; Copy character from source
    mov [di], al            ; Copy character to destination
    dec si              ; Decrement source pointer
    inc di              ; Increment result pointer
    dec cl              ; Decrement counter
    cmp cl,0            ; Take next if not done 
    jne coop                                          

; *********************** My code ends ***********************

; print both buffers
    lea     si,mystr
    call    print_string    ; Print mystr
    lea     si,endl
    call    print_string    ; Print cr+lf

    lea     si,mystrREV
    call    print_string    ; Print mystrREV
    lea     si,endl         ; CODE DOESN'T PRINT ENOUGH
    call    print_string    ;print cr+lf

; compare strings. If equal => palindrome
    mov     cl,length   ; # of characters in buffers 
    lea     si,mystr    ; address of first buffer
    lea     di,mystrREV ; address of second buffer
niis:   cmp cl,0        ; test if end-of-comparison/buffer 

; *********************** My code starts ********************* 

    je      positive        ; jump to ok, palindrome/empty buffer   
    lea     si,mystr        ; Source buffer address
    lea     di,mystrREV     ; Result buffer address
    cmp     di,si           ; Are same, still chance?
    jne     negative        ; Nop, jump to print NOT-message and exit
    inc     si              ; increment source pointer
    inc     di              ; increment destination pointer
    dec     cl              ; decrement counter

; *********************** My code ends ***********************

    jmp     niis    ; Try next

positive: lea   si,msg3     ; Yess, palindrome
    call    PRINT_STRING    ; Print it
    jmp bort                ; and exit

negative: lea   si,msg2     ; NOT a palindrome
    call    PRINT_STRING    ; Print it and exit

bort:   mov ax,4c00h        ; code for return to ms-dos
    int 21h                 ; call ms-dos terminate program
    ret

; Macro definitions
DEFINE_GET_STRING
DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
    end                     ;END-OF-PROGRAM

My result:

Enter a string (max 128 characters): abba
abba
a

The string is NOT a palindrome.

Console view

Expected result:

Enter a string (max 128 characters): innostunutsonni
innostunutsonni
innostunutsonni

The string is a palindrome.

Console view

We're using this old emulator software called emu8086 which has some documentation online. Any help would be highly appreciated! Thank you.


Solution

  • Problem 1 (improved)

    ; *********************** My code starts *********************  
    ; Something goes wrong in this code block   
    lea di, mystrREV        ; Result buffer address into DI
    lea si, mystr       ; Source buffer address id SI(decremented)
    coop:
    mov al, [si]   ; Copy character from source
    mov [di], al            ; Copy character to destination
    dec si              ; Decrement source pointer
    inc di              ; Increment result pointer
    dec cl              ; Decrement counter
    cmp cl,0            ; Take next if not done 
    jne coop                                          
    ; *********************** My code ends **********************
    

    You should have taken the hint in the comment "; Source buffer address id SI(decremented)".

    In order to traverse the source string backwards - that's what 'decremented' means - you need to initialize the source pointer SI to the end of the string. That means that you need to compute StartOfString + LengthOfString - 1.

    ; *********************** My code starts *********************  
    lea di, mystrREV    ; Result buffer address into DI
    lea bx, mystr       ; Source buffer address id SI(decremented)
    add bl, cl
    adc bh, 0
    lea si, [bx-1]
    coop:
    mov al, [si]        ; Copy character from source
    mov [di], al        ; Copy character to destination
    dec si              ; Decrement source pointer
    inc di              ; Increment result pointer
    dec cl              ; Decrement counter
    jne coop            ; Take next if not done                                           
    ; *********************** My code ends **********************
    

    Please notice that you don't need that cmp cl,0 instruction because the preceding dec cl instruction already set the necessary flags.

    Problem 2 (new)

    ; compare strings. If equal => palindrome
    mov     cl,length   ; # of characters in buffers 
    lea     si,mystr    ; address of first buffer
    lea     di,mystrREV ; address of second buffer
    niis:
    cmp cl,0        ; test if end-of-comparison/buffer 
    ; *********************** My code starts ********************* 
    je      positive        ; jump to ok, palindrome/empty buffer   
    lea     si,mystr        ; Source buffer address
    lea     di,mystrREV     ; Result buffer address
    cmp     di,si           ; Are same, still chance?
    jne     negative        ; Nop, jump to print NOT-message and exit
    inc     si              ; increment source pointer
    inc     di              ; increment destination pointer
    dec     cl              ; decrement counter
    ; *********************** My code ends ***********************
    

    Your code to compare the strings does not compare at all! The comments they gave are misleading.

    You don't want the addresses again in SI and DI. You need to fetch the characters that this registers point at and then compare those:

    ; *********************** My code starts ********************* 
    je      positive   
    mov     al, [si]        ; Source buffer address   <<<<< misleading comment
    mov     dl, [di]        ; Result buffer address   <<<<< misleading comment
    cmp     al, dl          ; Are same, still chance?
    jne     negative