Garbage in output and wrong strings printed - string

I'm using nasm , and I have to do this assembly program for class that is supposed to receive a password, compare with the one stored in pass, and write whatever the password is valid or not, however for some odd reason, when printing cade it yields garbage along with the string, and when to print the other two it prints cade instead along with contr and garbage, so I'm not really sure what's happening, and if someone could help me I would really appreciate it.
Here is the macro I use to print the string
%macro inout 2
mov ah,%2
mov dx,%1
int 21h
%endmacro
And here is the program
[bits 16]
%include "macros2.inc"
[segment .data]
cade: db 'Enter the password',0ah, 0dh,'$'
invalida: db 'wrong password',0ah, 0dh,'$'
valida: db 'valid password',0ah, 0dh,'$'
pass: db '12345$'
band: db 0
contr: resb 10
[segment .code]
..start
mov ax,data
mov dx,ax
inout cade,09h
mov bx,contr
mov ah,09h
mov dx,cade
int 21h
leer:
mov ah,08h
int 21h
cmp al,0dh
je checa
mov [bx],al
inc bx
mov ah,02h
mov dl, "*"
int 21h
jmp leer
checa:
lea di,[contr]
lea si, [pass]
dec si
revisa:
loadsb
inc di
cmp [di],al
jne error
inc bx
inc di
cmp si,'$'
jl revisa
mov ah,09h
mov dx,valida
int 21h
jmp fin
error:
mov ah,09h
mov dx,invalida
int 21h
fin:
mov ah,4ch
int 21h
[bits 16]
%include "macros2.inc"
[segment .data]
cade: db 'Introduzca la contrsena',0ah, 0dh,'$'
invalida: db 'Contraseña no Valida',0ah, 0dh,'$'
valida: db 'Contraseña valida',0ah, 0dh,'$'
pass: db '12345$'
band: db 0
contr: resb 10
[segment .code]
..start
mov ax,data
mov dx,ax
inout cade,09h
mov bx,contr
mov ah,09h
mov dx,cade
int 21h
leer:
mov ah,08h
int 21h
cmp al,0dh
je checa
mov [bx],al
inc bx
mov ah,02h
mov dl, "*"
int 21h
jmp leer
checa:
lea di,[contr]
lea si, [pass]
dec si
revisa:
loadsb
inc di
cmp [di],al
jne error
inc bx
inc di
cmp si,'$'
jl revisa
mov ah,09h
mov dx,valida
int 21h
jmp fin
error:
mov ah,09h
mov dx,invalida
int 21h
fin:
mov ah,4ch
int 21h}

Doesn't take long to find your first problem...
[segment .code]
..start
mov ax,data
mov dx,ax
I think you want that to be ds, not dx.
I see you reinvent gets(). How about checking that you don't overflow your buffer?
It isn't too clear what you're trying to do after that. How about some comments?

Related

Need help combining two strings TASM

I need help in combining two programs I have and I can't seem to get it working for me. Don't get the desired output.
So here's my problem statement:
Combine Two separate strings in a third string and display it, Where the first String is as it is and the second string is reversed.
Example:
Input:
String 1: 'Hello'
String 2: '.dlroW '
Output:
'Hello World.'
end of Example.
Now there are two ways we can go about this.
First: Use string functions.(Preferred)
Now I am fairly new to learning Assembly Language so I would like to do it using string functions so I can learn something New.
Second: Without using string functions.
Another Approach is if someone can help combining two programs, One for the concatenation of the string and the other for reversal, Note that I have written the two individual programs and they run well without any hiccups, I just can't seem to do it together. How I am going about with this is before concatenating the string I am trying to reverse it, then proceeding with the addition of the second string. But I can't seem to get it working. I've tried to the best of my knowledge.
//Concatenation Code
.model tiny
.data
msg1 db 10,13,"Enter the string 1: $"
cat db 30 DUP('$')
msg2 db 10,13,"Enter the string 2: $"
msg3 db 10,13,"Concatenated string is: $"
.code
mov ax,#data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
lea si,cat
up: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up
lea dx,msg2
mov ah,09h
int 21h
dec si
up1: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up1
lea dx,msg3
mov ah,09h
int 21h
lea dx,cat
mov ah,09h
int 21h
mov ah,4ch
int 21h
end`
Here's Part 2
//Reversal Code
.model tiny
.data
msg1 db 10,13,"enter the string: $"
string db 40 DUP('$')
rev db 40 DUP('$')
msg2 db 10,13,"reverse string is: $"
.code
mov ax,#data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
mov ah,0ah
lea dx,string
int 21h
lea si,string
lea di,rev
mov cl,[si+1]
mov ch,00h
add di,cx
inc si
inc si
up: mov al,[si]
mov [di],al
inc si
dec di
loop up
inc di
mov ah,09h
lea dx,msg2
int 21h
mov ah,09h
lea dx,[di]
int 21h
mov ah,4ch
int 21h
end
And Here is the code I came Up with by combining those two.
//That's the code I tried Combining
.model tiny
.data
.model tiny
.data
msg1 db 10,13,"Enter string1: $"
cat db 30 DUP('$')
msg2 db 10,13,"Enter string2: $"
msg3 db 10,13,"Concatenated string is: $"
.code
mov ax, #data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
lea si,cat
up: mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up
lea dx, msg2
mov ah,09h
int 21h
dec si
up2:mov al,[si]
mov [di],al
inc si
dec di
loop up2
inc di
up1:mov ah,01h
int 21h
mov [si],al
inc si
cmp al,0dh
jnz up1
lea dx,msg3
mov ah,09h
int 21h
lea dx,cat
mov ah,09h
int 21h
mov ah,4ch
int 21h
end
My Output
As you can see clearly I have failed at doing either task correctly. So can someone tell me where I am going wrong? Or teach me how to do this using the string Functions?
The up2 loop that tries to do string reversal comes too soon!. You've placed it where the 2nd string (the one that needs reversal) isn't even inputted yet.
If you would have written comments in your program, then you would probably have noticed this yourself.
This up2 loop uses the LOOP instruction that depends on the CX register but your program does not assign any suitable value to CX.
And also your working reversal program is using 2 buffers. Why then do you expect the combo to work from a single buffer?
Define the cat buffer so it can hold both strings.
Define the str buffer so it can hold the second string.
lea dx, msg1
mov ah, 09h ; DOS.PrintString
int 21h
lea di, cat
up: ; Input f i r s t string
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
mov [di], al
inc di
cmp al, 13
jne up
dec di ; Throw out the 13
; This marks the start of the reversed string, VERY IMPORTANT
; So don't change DI while inputting the 2nd string
lea dx, msg2
mov ah, 09h ; DOS.PrintString
int 21h
lea si, str
mov dx, si
up1: ; Input s e c o n d string
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
mov [si], al
inc si
cmp al, 13
jne up1
dec si ; Throw out the 13
cmp si, dx
je done ; Second string was empty. CAN HAPPEN!
up2: ; Reversed copying of s e c o n d string
dec si
mov al, [si]
mov [di], al
inc di
cmp si, dx
ja up2
done:
mov ax, 0A0Dh ; Add a proper carriage return and linefeed to the result
mov [di], ax
mov al, '$' ; Terminate the result with a dollar sign
mov [di+2], al
lea dx, msg3
mov ah, 09h ; DOS.PrintString
int 21h
lea dx, cat
mov ah, 09h ; DOS.PrintString
int 21h
First: Use string functions.(Preferred)
Both in the up loop and in the up2 loop, do you find next pair of instructions:
mov [di], al
inc di
Provided
the direction flag DF is clear so that DI can increment
the ES segment register points to #data
you can replace these 2 instructions by a single STOSB instruction.
This is what needs to go on top of your program:
.code
mov ax, #data
mov ds, ax
mov es, ax
cld
If we allowed ourselves to write a silly sequence of multiple std (set direction flag) and cld (clear direction flag) instructions, we could also replace mov al, [si] with lodsb. Care must be taken to keep a valid SI pointer (*).
dec si ; (*)
up2: ; Reversed copying of s e c o n d string
std
lodsb ; Due to STD, SI will decrement
cld
stosb ; Due to CLD, DI will increment
cmp si, dx
jae up2 ; (*)
done:
mov ax, 0A0Dh ; Add a proper carriage return and linefeed to the result
stosw
mov al, '$' ; Terminate the result with a dollar sign
stosb
In code that sets the direction flag (using std) it is best to end with a cld instruction so the direction flag is in the state we most expect!

How to convert String to Number in 8086 assembly?

I have to build a Base Converter in 8086 assembly .
The user has to choose his based and then put a number,
after then , the program will show him his number in 3 more bases[he bring a decimal number, and after this he will see his number in hex, oct, and bin.
This first question is, how can I convert the number he gave me, from string, to a number?
the sec question is, how can i convert? by RCR, and then adc some variable?
Here is my code:
data segment
N=8
ERROR_STRING_BASE DB ,10,13, " THIS IS NOT A BASE!",10,13, " TRY AGINE" ,10,13," $"
OPENSTRING DB " Welcome, to the Base Convertor",10,13," Please enter your base to convert from:",10,13," <'H'= Hex, 'D'=Dec, 'O'=oct, 'B'=bin>: $"
Hex_string DB "(H)" ,10,13, "$"
Octalic_string DB "(O) ",10,13, "$"
Binar_string DB "(B)",10,13, "$"
Dece_string DB "(D)",10,13, "$"
ENTER_STRING DB ,10,13, " Now, Enter Your Number (Up to 4 digits) ",10,13, "$"
Illegal_Number DB ,10,13, " !!! This number is illegal, lets Start again" ,10,13,"$"
BASED_BUFFER DB N,?,N+1 DUP(0)
Number_buffer db N, ? ,N+1 DUP(0)
TheBase DB N DUP(0)
The_numer DB N DUP(0)
The_binNumber DB 16 DUP(0)
data ends
sseg segment stack
dw 128 dup(0)
sseg ends
code segment
assume ss:sseg,cs:code,ds:data
start: mov ax,data
mov ds,ax
MOV DX,OFFSET OPENSTRING ;PUTS THE OPENING SRTING
MOV AH,9
INT 21H
call EnterBase
CALL CheckBase
HEXBASE: CALL PRINTtheNUMBER
MOV DX,OFFSET Hex_string
MOV AH,9
INT 21h
JMP I_have_the_numberH
oCTALICbASE: CALL PRINTtheNUMBER
MOV DX,OFFSET Octalic_string
MOV AH,9
INT 21h
JMP I_have_the_numberO
BINBASE:CALL PRINTtheNUMBER
MOV DX,OFFSET Binar_string
MOV AH,9
INT 21h
JMP I_have_the_numberB
DECBASE: CALL PRINTtheNUMBER
MOV DX,OFFSET Dece_string
MOV AH,9
INT 21h
JMP I_have_the_numberD
I_have_the_numberH: CALL BINcalculation
CALL OCTcalculation
CALL DECcalculation
I_have_the_numberO: CALL BINcalculation
CALL DECcalculation
CALL HEXcalculation
I_have_the_numberB: CALL OCTcalculation
CALL DECcalculation
CALL HEXcalculation
I_have_the_numberD: CALL BINcalculation
CALL OCTcalculation
CALL HEXcalculation
exit: mov ax, 4c00h
int 21h
EnterBase PROC
MOV DX,OFFSET BASED_BUFFER ; GETS THE BASE
MOV AH,10
INT 21H
LEA DX,BASED_BUFFER[2]
MOV BL,BASED_BUFFER[1]
MOV BH,0
MOV BASED_BUFFER[BX+2],0
LEA SI, BASED_BUFFER[2]
XOR CX, CX
MOV CL, BASED_BUFFER[1]
LEA DI, TheBase
LOL_OF_BASE: MOV DL, [SI]
MOV [DI], DL
INC SI
INC DI
INC AL
RET
EnterBase ENDP
CheckBase proc
CMP TheBase,'H'
JE HEXBASE
CMP TheBase,'h'
JE HEXBASE
CMP TheBase,'O'
JE oCTALICbASE
CMP TheBase,'o'
JE oCTALICbASE
CMP TheBase,'B'
JE BINBASE
CMP TheBase,'b'
JE BINBASE
CMP TheBase,'D'
JE DECBASE
CMP TheBase,'d'
JE DECBASE
CMP TheBase, ' '
je ERRORoFBASE
ERRORoFBASE: MOV DX,OFFSET ERROR_STRING_BASE ;PUTS WORNG BASE Illegal_Number
MOV AH,9
INT 21H
JMP START
CheckBase ENDP
PRINTtheNUMBER PROC
MOV DX,OFFSET ENTER_STRING
MOV AH,9
INT 21h
MOV DX,OFFSET Number_buffer ; GETS THE number
MOV AH,10
INT 21H
LEA DX,Number_buffer[2]
MOV BL,Number_buffer[1]
MOV BH,0
MOV Number_buffer[BX+2],0
LEA SI, Number_buffer[2]
XOR CX, CX
MOV CL, Number_buffer[1]
LEA DI, The_numer
xor AL,AL
LOL_OF_NUMBER_CHECK: MOV DL, [SI]
MOV [DI], DL
INC SI
INC DI
INC AL
CMP AL,5
JE ERRORofNUMBER
LOOP LOL_OF_NUMBER_CHECK
RET
ERRORofNUMBER: MOV DX,OFFSET Illegal_Number ;PUTS WORNG BASE Illegal_Number
MOV AH,9
INT 21H
JMP START
PRINTtheNUMBER ENDP
PROC BINcalculation
XOR CX,CX
XOR AX,AX
MOV CX,4
MOV AX,16
LEA SI, The_binNumber[0]
TheBinarLoop: RCL The_numer,1
ADC [SI],0
INC SI
LOOP TheBinarLoop
ENDP
PROC OCTcalculation
ENDP
PROC DECcalculation
ENDP
PROC HEXcalculation
ENDP
code ends
end start
It should be look like this:
thanks!
שלו לוי
the algorighm to decode ascii strings from ANY base to integer is the same:
result = 0
for each digit in ascii-string
result *= base
result += value(digit)
for { bin, oct, dec } value(digit) is ascii(digit)-ascii('0')
hex is a bit more complicated, you have to check if the value is 'a'-'f', and convert this to 10-15
converting integer to ascii(base x) is similar, you have to divide the value by base until it's 0, and add ascii representation of the remainder at the left
e.g. 87/8= 10, remainder 7 --> "7"
10/8= 1, remainder 2 --> "27"
1/8= 0, remainder 1 --> "127"
Copy-paste next little program in EMU8086 and run it : it will capture a number as string from keyboard, then convert it to numeric in BX. To store the number in "The_numer", you have to do mov The_numer, bl :
.stack 100h
;------------------------------------------
.data
;------------------------------------------
msj1 db 'Enter a number: $'
msj2 db 13,10,'Number has been converted',13,10,13,10,'$'
string db 5 ;MAX NUMBER OF CHARACTERS ALLOWED (4).
db ? ;NUMBER OF CHARACTERS ENTERED BY USER.
db 5 dup (?) ;CHARACTERS ENTERED BY USER.
;------------------------------------------
.code
;INITIALIZE DATA SEGMENT.
mov ax, #data
mov ds, ax
;------------------------------------------
;DISPLAY MESSAGE.
mov ah, 9
mov dx, offset msj1
int 21h
;------------------------------------------
;CAPTURE CHARACTERS (THE NUMBER).
mov ah, 0Ah
mov dx, offset string
int 21h
;------------------------------------------
call string2number
;------------------------------------------
;DISPLAY MESSAGE.
mov ah, 9
mov dx, offset msj2
int 21h
;------------------------------------------
;STOP UNTIL USER PRESS ANY KEY.
mov ah,7
int 21h
;------------------------------------------
;FINISH THE PROGRAM PROPERLY.
mov ax, 4c00h
int 21h
;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
mov si, offset string + 1 ;<================================ YOU CHANGE THIS VARIABLE.
mov cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.
mov ch, 0 ;CLEAR CH, NOW CX==CL.
add si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
mov bx, 0
mov bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:
;CONVERT CHARACTER.
mov al, [ si ] ;CHARACTER TO PROCESS.
sub al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
mov ah, 0 ;CLEAR AH, NOW AX==AL.
mul bp ;AX*BP = DX:AX.
add bx,ax ;ADD RESULT TO BX.
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
mov ax, bp
mov bp, 10
mul bp ;AX*10 = DX:AX.
mov bp, ax ;NEW MULTIPLE OF 10.
;CHECK IF WE HAVE FINISHED.
dec si ;NEXT DIGIT TO PROCESS.
loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.
ret
endp
The proc you need is string2number. Pay attention inside the proc : it uses a variable named "string", you have to change it by the name of your own variable. After the call the result is in BX: if the number is less than 256, you can use the number in BL.
By the way, the string is ALWAYS converted to a DECIMAL number.

String buffer in assembly code

I just have ended my code which allow to cover your password. It goes like this(FASM):
org 100h
mov cx, 16
petla:
mov ah,08h
int 21h
cmp al,0dh
je OK
mov ah,02h
mov dl,42
int 21h
cmp cx,0
je Fail
loop petla
Fail:
mov dl, 0ah
int 21h
mov dx, pass2
mov ah,9
int 21h
jmp koniec
OK:
mov dl, 0ah
int 21h
mov dx, pass
mov ah,9
int 21h
jmp koniec
koniec:
mov ah,4ch
int 21h
pass db 'Password OK', 0Ah, 0Dh, '$'
pass2 db 'Password Fail', 0Ah, 0Dh, '$'
And now I need to print the genuine password. I know the string buffer is a must and how declaration of the buffer should look like but I don't really know how to use it and make it work.
Calling for help :)
Cheers.
Since your program allows the input of 15 characters of password, you could setup the buffer with:
Buffer db 16 dup ("$")
You initialize the DI register before your petla loop and put the ASCII code you got from the DOS function in the buffer via a stosb instruction:
mov di, Buffer
mov cx, 16
petla:
mov ah,08h
int 21h
cmp al,0dh
je OK
stosb
mov ah,02h
mov dl,42
int 21h
;;;cmp cx,0
;;;je Fail
loop petla
Please note that compairing for CX=0 is useless just before the loop instruction in your code.

Reversing a string in assembly language 80x86

In a program I am currently doing, I have to reverse a string a user has entered. I have to leave the word that the user entered in where I prompted them to enter it and right below it I want to print out the word in reverse. When I try to run it in DOSBox with the Tasm compiler it gives me an error that says "Illegal memory reference" on line 189 which is the line that contains the variable I plan to put the reversed word in. Can someone help me find out what I am doing wrong? I would greatly appreciate it! Also only in my program there are 4 boxes. The first box I try to print the reverse word below the prompt. The rest of the boxes prints the user entered word instead of the reversed version of it.
title fill in title ;program name
;------------------------------------------------------------------
stacksg segment para stack 'Stack' ;define the stack
db 32 dup(0) ;32 bytes, might want larger
stacksg ends
;------------------------------------------------------------------
datasg segment para 'Data' ;data segment
paralst Label Byte
maxlen db 21
actlen db ?
dbdata db 21 dup('$')
outit db 'Enter String: $' ;14 chars minus $
switch db 21 dup('$')
datasg ends
;------------------------------------------------------------------
codesg segment para 'Code' ;code segment
main proc far ;main procedure
assume ss:stacksg, ds:datasg, cs:codesg ;define segment registers
mov ax, datasg ;initialize data segment register
mov ds, ax
;--------------- --------------------------top left corner
mov ah, 06h
mov al, 00
mov bh, 01000001b ; 4eh
mov ch, 0
mov cl, 0
mov dl, 39
mov dh, 12
int 10h
;-------------------------------------------top right corner
mov ah, 06h
mov al, 0
mov bh, 11110010b
;mov cx, 0c00h
;mov dx, 184fh
mov ch, 0
mov cl, 39
mov dh, 12
mov dl, 79
int 10h
;--------------------------------------------bottom left corner
mov ah, 06h
mov al, 0
mov bh, 11100100b ;yellow
mov ch, 12
mov cl, 0
mov dh, 24
mov dl, 39
int 10h
;------------------------------------------bottom right corner
mov ah, 06h
mov al, 0
mov bh, 01011111b ; magenta 80
mov ch, 12
mov cl, 39
mov dh, 24
mov dl, 79
int 10h
;--------------------------------------------------- 1st quad
mov ah, 02h
mov bh, 0
mov dh, 5
mov dl, 5
int 10h
mov ah, 09h
lea dx, outit
int 21h
;------------------------------------input
mov ah, 0ah
lea dx, paralst
int 21h
; -----------------------------------move cursor
mov ah, 02h
mov bh, 0
mov dh, 7
mov dl, 5
int 10h
call REVERSE
;--------------------------------------print output
mov ah, 09h
lea dx, switch
int 21h
;----------------------------------------------------2nd quad
mov ah, 02h
mov bh, 0
mov dh, 5
mov dl, 44
int 10h
mov ah, 09h
lea dx, outit
int 21h
;------------------------------------input
mov ah, 0ah
lea dx, paralst
int 21h
; -----------------------------------move cursor
mov ah, 02h
mov bh, 0
mov dh, 7
mov dl, 44
int 10h
;--------------------------------------print output
mov ah, 09h
lea dx, dbdata
int 21h
;------------------------------------------------------3rd quad
mov ah, 02h
mov bh, 0
mov dh, 17
mov dl, 5
int 10h
mov ah, 09h
lea dx, outit
int 21h
;------------------------------------input
mov ah, 0ah
lea dx, paralst
int 21h
; -----------------------------------move cursor
mov ah, 02h
mov bh, 0
mov dh, 19
mov dl, 5
int 10h
;--------------------------------------print output
mov ah, 09h
lea dx, dbdata
int 21h
;------------------------------------------------------4th quad
mov ah, 02h
mov bh, 0
mov dh, 17
mov dl, 44
int 10h
mov ah, 09h
lea dx, outit
int 21h
;------------------------------------input
mov ah, 0ah
lea dx, paralst
int 21h
; -----------------------------------move cursor
mov ah, 02h
mov bh, 0
mov dh, 19
mov dl, 44
int 10h
;--------------------------------------print output
mov ah, 09h
lea dx, dbdata
int 21h
mov ax, 4c00h ;end processing
int 21h
main endp ;end of procedure
;----------------------------------------reverse procedure
REVERSE PROC NEAR
mov cx, 0
;-----figure out actlen here
mov actlen, 0
lea bx, dbdata ;may need to use paralst instead
hi: cmp [bx], '$'
jne sup
inc actlen
inc bx
jmp hi
sup:
;------------
mov cx, 0
mov cl, actlen
lea bx, dbdata
add bx, cx
yo: cmp actlen, 0
je hola
mov switch, byte ptr[bx]
dec bx
inc switch
dec actlen
jmp yo
hola:
RET
REVERSE ENDP
codesg ends ;end of code segment
end main ;end of program
You can't do mov memory, memory. Move the source into a register first, then place it at the destination.Also, inc switch doesn't do what you seem to think it's doing. You can't change the address of switch at runtime, so what's actually happening there is that you're incrementing the first element at switch (as if you had written inc [switch]). If you need to modify an address; again, put it in a register.
So for example:
lea si, dbdata
add si,cx
lea di, switch
mov al,[bx]
jcxz hola ; jump if cx == 0
cld ; clear the direction flag; for stosb
yo: mov al,[si]
stosb ; [di++] = al
dec si
loop yo ; if (--cx) jmp yo
hola:
I didn't look at the entire piece of code, so it's unclear to me whether your reverse is supposed to copy the terminator ('$') or not. If it should, you should always execute the loop at least once (and then you don't need the jcxz). If it shouldn't, you should set the source address to dbdata + cx - 1 instead of dbdata + cx.

how to check compare if palindrome or not?

I don't know much of assembly language but I tried making this palindrome and it's quite hard. First I have to enter a string then show its original and reversed string then show if its a palindrome or not.
I already figured out how to show the reverse string by pushing and popping it through a loop from what I have read in another forum and figured it out
now the only problem for me is to compare the reverse string and original string to check if its a palindrome or not.
call clearscreen
mov dh, 0
mov dl, 0
call cursor
mov ah, 09h
mov dx, offset str1
int 21h
palin db 40 dup(?)
mov ah, 0ah
mov palin, 40
mov dx, offset palin
int 21h
mov dh, 1
mov dl, 0
call cursor
mov ah, 09h
mov dx, offset str2
int 21h
mov si, 2
forward:
mov al, palin + si
cmp al, 13
je palindrome
mov ah, 02h
mov dl, al
push ax 'push the letter to reverse
int 21h
inc si
jmp forward
palindrome:
mov dh, 2
mov dl, 0
call cursor
mov ah, 09h
mov dx, offset str3
int 21h
mov cx, 40 'pop each letter through a loop to show its reverse
reverse:
mov ah, 02h
pop ax
mov dl, al
int 21h
loop reverse
int 20h
clearscreen:
mov ax, 0600h
mov bh, 0Eh
mov cx, 0
mov dx, 8025
int 10h
ret
cursor:
mov ah, 02h
mov bh, 0
int 10h
ret
str1: db "Enter A String : $"
str2: db "Forward : $"
str3: db "Backward : $"
str4: db "Its a Palindrome! $"
str5: db "Not a Palindrome!$"
You have a string the user typed in, what you need to do is compare the first byte with the last byte, do the same for the 2nd one and the 2nd to last one. Keep doing this for the whole string. You also need the length of the string. To make life easier, you should convert the string to all UPPER case letters or all lowercase letters to make comparison easier.
It is unfortunate they are still teaching 16bit DOS code. This is a sample with the word defined in the data section. You will have to modify it to receive input and work on that string
.data
pal db "racecar"
pal_len equ $ - pal - 1
szYes db "yes$"
szNo db "no$"
.code
start:
mov ax,#data
mov ds,ax
call IsPalindrome
mov ah,4ch
int 21h
IsPalindrome:
lea si, pal
lea di, pal
add di, pal_len
mov cx, 0
CheckIt:
mov al, byte ptr [si]
mov dl, byte ptr [di]
cmp al, dl
jne No
inc si
dec di
inc cx
cmp cx, pal_len
jne CheckIt
mov ah,9
lea dx,szYes
int 21h
ret
No:
mov ah,9
lea dx,szNo
int 21h
ret
end start
For completeness and to bring us into the 21st century, 32bit NASM code:
section .data
fmt db "%s", 0
szPal db "RACECAR"
Pal_len equ $ - szPal - 1
szYes db "Yes", 10, 0
szNo db "No", 10, 0
extern printf, exit
global _start
section .text
_start:
call IsPalindrome
call exit
IsPalindrome:
mov ecx, 0
mov ebx, Pal_len
mov esi, szPal
.CheckIt:
mov al, byte [esi + ecx]
mov dl, byte [esi + ebx]
cmp al, dl
jne .No
inc ecx
dec ebx
jns .CheckIt
push szYes
push fmt
call printf
add esp, 4 * 2
mov eax, 1
jmp Done
.No:
push szNo
push fmt
call printf
add esp, 4 * 2
xor eax, eax
Done:
ret

Resources