Sorting strings in 8086 Assembly - string

I want to write a 8086 assembly program that takes 5 strings from the user as an input and then sorts these strings and prints the sorted result as an output. I actually do everything but I have a big problem with the sorting part. I know how to use a for example bubble sort to sort the items in an array that start from a specific address but here I have 5 different strings that are not in the same array. each string has its own address and its own characters. I try to compare last character of each string with each other and then if one is bigger that another one i swap the whole string and then I go on and do that for the whole characters of all string to the first.
For example if our input strings are:
eab
abe
cbd
cda
adb
I will first sort the last character of every string and I come up with this:
cda
eab
adb
cbd
abe
Then I will compare them by the middle character:
eab
cbd
abe
cda
adb
and at last with the first character and everything is sorted:
abe
adb
cbd
cda
eab
but it is actually what in my mind and I don't have any idea who to implement that for my job.
; multi-segment executable file template.
data segment
data1 db 64,?,64 dup(?)
data2 db 64,?,64 dup(?)
data3 db 64,?,64 dup(?)
data4 db 64,?,64 dup(?)
data5 db 64,?,64 dup(?)
change db 66 dup(?)
msg db 0ah,0dh,"You enter a wrong option",0ah,0dh,"try again",0ah,0dh,"$"
prompt db 0ah,0dh,"Choose an option:",0ah,0dh,"$"
prompt1 db ".a: Sort in ascending order",0ah,0dh,"$"
prompt2 db ".d: Sort in descending order",0ah,0dh,"$"
prompt3 db ".q: Quit",0ah,0ah,0dh,"$"
enter db 0ah,0ah,0dh,"Enter 5 strings:",0ah,0dh,"$"
pkey db 0ah,0dh,"press any key...$"
ends
stack segment
dw 128 dup(0)
ends
code segment
main proc far
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
again:
; printing the prompts for the user
lea dx, prompt
mov ah, 09h
int 21h
lea dx, prompt1
mov ah, 09h
int 21h
lea dx, prompt2
mov ah, 09h
int 21h
lea dx, prompt3
mov ah, 09h
int 21h
; getting a character from the user as an input
mov ah, 01h
int 21h
; determining which option the user selects
cmp al, 'a'
je ascending
cmp al, 'd'
je descending
cmp al, 'q'
je quit
; this is for the time that the user enters a wrong char
lea dx, msg
mov ah, 09h
int 21h
jmp again ; again calling the application to start
ascending:
call input
call AscendSort
jmp again ; again calling the application to start
descending:
call input
call DescendSort
jmp again ; again calling the application to start
quit:
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
main endp
;.................................................
; this subroutine gets input from user
input proc
lea dx, enter
mov ah, 09h
int 21h
call newline
mov ah, 0ah
lea dx, data1
int 21h
call newline
mov ah, 0ah
lea dx, data2
int 21h
call newline
mov ah, 0ah
lea dx, data3
int 21h
call newline
mov ah, 0ah
lea dx, data4
int 21h
call newline
mov ah, 0ah
lea dx, data2
int 21h
call newline
ret
input endp
;................................................
; sorting the strings in the ascending order
AscendSort proc
mov si, 65
lea dx, change
mov al, data1[si]
cmp al, data2[si]
ja l1
?????
ret
AscendSort endp
;................................................
; sorting the strings in the descending order
DescendSort proc
ret
DescendSort endp
;................................................
; newline
newline proc
mov ah, 02h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
ret
newline endp
ends
end main ; set entry point and stop the assembler.
Any other algorithm for sorting these whole strings also will be appreciated.

I actually figure out the answer myself, I use string commands to compare the strings 2 by 2 with each other to see if they're bigger, smaller or equal. Something like the code below in the specific macro that takes two strings to check them and do the required operation like swapping the strings to make them sorted:
check macro a, b
local next, finish
cld
mov cx, 64 ; the size of our buffer that saves the string
mov si, a
mov di, b
repe cmpsb ; comparing two strings with each other
ja next
jmp finish
next:
; swaping our strings if needed
mov cx, 64
mov si, a
lea di, change
rep movsb
mov cx, 64
mov si, b
mov di, a
rep movsb
mov cx, 64
lea si, change
mov di, b
rep movsb
finish:
endm

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!

Is there a method to CMP two strings using emu8086?

I am working on a project to organize students mark in 3 exam using assembly language.
I want the emu to CMP the user's string by the ones in the text file, so if ZF set to 1, the emu will print the hole student's information (ID, Full Name, exams marks), that came from the compassion.
Here is the code, I take help from you guys.
ORG 100H
MOV DX, OFFSET MSG1
MOV AH, 9H
INT 21H
MOV DX, OFFSET MSG2
MOV AH, 9H
INT 21H
MOV DX, OFFSET LNBF ; GET STRING FROM USER
MOV AH, 0AH
INT 21H
MOV AL, 0 ; OPEN MY FILE
MOV DX, OFFSET FILE
MOV AH, 3DH
INT 21H
; READ FROM FILE
MOV BX, AX ; MOV HANDLER TO BX
MOV CX, 1 ; READ CHAR ONE BY ONE
LEA DX, DATABF
INT 21H
RET
FILE DB "MY.txt",0
LNBF DB 1EH,?
MSG1 DB "FIND A STUDENT BY HIS/HER LAST NAME:$"
MSG2 DB 0DH,0AH,0DH,0AH,"ENTER THE STUDENT'S LAST NAME->: $"
DATABF DW 0FFFH
Do correct these errors before you continue:
LNBF DB 1EH,? does a bad job setting up a buffer to input the student's name!
It overwrites MSG1 instead of providing a decent dedicated buffer.
The correct way is : LNBF DB 30, 0, 30 dup (0)
For detailed info about the DOS.BufferedInput function 0Ah see
How buffered input works
Your READ FROM FILE code forgets to specify the required function number 3Fh.
Use mov ah, 3Fh. Also you should not neglect the possibility that an error is returned via the carry flag!
Below is an example that you can use. It compares the carriage return-terminated name in the inputbuffer with the zero-terminated name in the text file. (The file could of course be using any string terminator that suits you...)
mov si, offset LNBF + 2 ; -> SI is address of student's name.
More:
call ReadOneCharFromFile ; -> AL
cmp al, 0
je SkipToNextNameInFile
cmp al, [si]
jne SkipToNextNameInFile
inc si
cmp byte [si], 13
jne More
call ReadOneCharFromFile ; -> AL
cmp al, 0
jne SkipToNextNameInFile
MatchFound:
...
SkipToNextNameInFile:
...

Reversing an input string in Assembly

I have this assembly code that reverses a string that I input. It only accepts maximum 20 characters. My problem is that when I hit enter to see the output there is an extra character at the end of the reversed string.
Please help me understand why that does occur and how I can remove that in the output.
We're required to only use function 09H int 21h to display the string and function 0Ah int 21h to input the string. We're using TASM.
Your help would be very much appreciated. Thank you.
Here is my code:
.model small
.stack 100h
.data
MSG DB "Input String(max 20 chars): ", 10, 13, "$"
Sentence1 DB 21,?,21 dup("$")
str2 dw 21 dup("$")
.code
start:
mov ax, #data
mov ds, ax
;Getting the string input
mov ah,09h
lea dx, MSG
int 21h
lea si,Sentence1
mov ah,0ah
mov dx,si
int 21h
;Reverse String
mov cl,Sentence1
add cl,1
add si,2
loop1:
inc si
cmp byte ptr[si],"$"
jne loop1
dec si
lea di,str2
loop2:
mov al,byte ptr[si]
mov byte ptr[di],al
dec si
inc di
loop loop2
;Printing the reverse string
mov ah,09h
lea dx,str2
int 21h
mov ah, 4ch
int 21h
end start
str2 dw 21 dup("$")
Normally this would be using the db directive.
mov cl,Sentence1
add cl,1
The reversal loop uses CX as its loop counter, but you don't set it correctly!
The 2nd byte of the "Sentence1" input structure, contains the value that you want in the CX register. You don't need to search for any terminating character. Moreover if you did, you'd rather have to look for ASCII code 13 (carriage return) instead of '$'.
mov cl, [si + 1] ;Number of characters in the string
mov ch, 0 ;Make it a word because LOOP depends on CX (not just CL)
Setting up SI then becomes:
add si, 2 ;To the start of the string
add si, cx ;To the position after the string
dec si ;To the last character of the string
but shorter:
add si, cx
inc si
If ever the user didn't input any text, you will want to by-pass the reversal entirely! That's what the jcxz is for in next code:
lea si, Sentence1
mov ah, 0Ah
mov dx, si
int 21h
;Reverse String
mov cl, [si + 1]
mov ch, 0
add si, cx
inc si
lea di, str2
jcxz EmptyString ;By-pass the reversal entirely!
loop2:
mov al, byte ptr[si]
mov byte ptr[di], al
dec si
inc di
loop loop2
EmptyString:
;Printing the reverse string (could be empty)
mov ah, 09h
lea dx, str2
int 21h

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.

Getting string input and displaying input with DOS interrupts MASM

In MASM, I created a buffer variable to hold the user string input from keyboard. I am stuck on how to hold the string input into that buffer variable. I don't have any libraries linked like the irvine ones and want to do this with DOS interrupts. So far I have something along the lines of
.model small
.stack 100h
.data
buff db 25 dup(0), 10, 13
lbuff EQU ($ - buff) ; bytes in a string
.code
main:
mov ax, #data
mov ds, ax
mov ah, 0Ah ; doesn't work
mov buff, ah ; doesn't seem right
int 21h
mov ax, 4000h ; display to screen
mov bx, 1
mov cx, lbuff
mov dx, OFFSET buff
int 21h
mov ah, 4ch
int 21h
end main
I assume using 0Ah is correct as it is for reading array of input of buffered characters.
I made some changes to your code. First, the "buff" variable needs the three level format (max number of characters allowed, another byte for the number of characteres entered, and the buffer itself) because that's what service 0AH requires. To use service 0AH I added "offset buff" (as Wolfgang said). Here it is:
.model small
.stack 100h
.data
buff db 26 ;MAX NUMBER OF CHARACTERS ALLOWED (25).
db ? ;NUMBER OF CHARACTERS ENTERED BY USER.
db 26 dup(0) ;CHARACTERS ENTERED BY USER.
.code
main:
mov ax, #data
mov ds, ax
;CAPTURE STRING FROM KEYBOARD.
mov ah, 0Ah ;SERVICE TO CAPTURE STRING FROM KEYBOARD.
mov dx, offset buff
int 21h
;CHANGE CHR(13) BY '$'.
mov si, offset buff + 1 ;NUMBER OF CHARACTERS ENTERED.
mov cl, [ si ] ;MOVE LENGTH TO CL.
mov ch, 0 ;CLEAR CH TO USE CX.
inc cx ;TO REACH CHR(13).
add si, cx ;NOW SI POINTS TO CHR(13).
mov al, '$'
mov [ si ], al ;REPLACE CHR(13) BY '$'.
;DISPLAY STRING.
mov ah, 9 ;SERVICE TO DISPLAY STRING.
mov dx, offset buff + 2 ;MUST END WITH '$'.
int 21h
mov ah, 4ch
int 21h
end main
When 0AH captures the string from keyboard, it ends with ENTER (character 13), that's why, if you want to capture 25 characters, you must specify 26.
To know how many characters the user entered (length), access the second byte (offset buff + 1). The ENTER is not included, so, if user types 8 characters and ENTER, this second byte will contain the number 8, not 9.
The entered characters start at offset buff + 2, and they end when character 13 appears. We use this to add the length to buff+2 + 1 to replace chr(13) by '$'. Now we can display the string.
This is my code,maybe can help you.
;Input String Copy output
dataarea segment
BUFFER db 81
db ?
STRING DB 81 DUP(?)
STR1 DB 10,13,'$'
dataarea ends
extra segment
MESS1 DB 'After Copy',10,13,'$'
MESS2 DB 81 DUP(?)
extra ends
code segment
main proc far
assume cs:code,ds:dataarea,es:extra
start:
push ds
sub ax,ax
push ax
mov ax,dataarea
mov ds,ax
mov ax,extra
mov es,ax
lea dx,BUFFER
mov ah,0ah
int 21h
lea si,STRING
lea di,MESS2
mov ch,0
mov cl,BUFFER+1
cld
rep movsb
mov al,'$'
mov es:[di],al
lea dx,STR1 ;to next line
mov ah,09h
int 21h
push es
pop ds
lea dx,MESS1 ;output:after copy
mov ah,09h
int 21h
lea dx,MESS2
mov ah,09h
int 21h
ret
main endp
code ends
end start
And the result is:
c:\demo.exe
Hello World!
After Copy
Hello World!
You may follow this code :
; Problem : input array from user
.MODEL SMALL
.STACK
.DATA
ARR DB 10 DUB (?)
.CODE
MAIN PROC
MOV AX, #DATA
MOV DS, AX
XOR BX, BX
MOV CX, 5
FOR:
MOV AH, 1
INT 21H
MOV ARR[BX], AL
INC BX
LOOP FOR
XOR BX, BX
MOV CX, 5
PRINT:
MOV AX, ARR[BX] ;point to the current index
MOV AH, 2 ;output
MOV DL, AX
INT 21H
INC BX ;move pointer to the next element
LOOP PRINT ;loop until done
MAIN ENDP
;try this one, it takes a 10 character string input from user and displays it after in this manner, "Hello *10character string input"
.MODEL TINY
.CODE
.286
ORG 100h
START:
MOV DX, OFFSET BUFFER
MOV AH, 0ah
INT 21h
JMP PRINT
BUFFER DB 10,?, 10 dup(' ')
PRINT:
MOV AH, 02
MOV DL, 0ah
INT 21h
MOV AH, 9
MOV DX, OFFSET M1
INT 21h
XOR BX, BX
MOV BL, BUFFER[1]
MOV BUFFER [BX+2], '$'
MOV DX, OFFSET BUFFER +2
MOV AH, 9
INT 21h
M1: db 'Hello $'
END START
END

Resources