I need to write a program that will get a letters from the user (console), until the letter 'Z' is entered (example: ABCZ). Letters must be placed on the stack. After completing the input, the program should print the letters from the stack in the reverse order (example: CBA), and then once again print the letters from the stack in alphabetical order (example: ABC). I wrote the program, but the last part works incorrectly. The program does not display letters from the stack in alphabetical order, except the first letter. I wanted to continue using SP after displaying it in reverse order.
DATA SEGMENT
MESSAGE DB "ENTER CHARACTER :$"
DATA ENDS
SSEG SEGMENT STACK
DB 100H DUP (?)
SSEG ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:SSEG
START:
MOV AX,DATA
MOV DS,AX
LEA DX,MESSAGE ;print String or Message present in the
MOV AH,9 ;character Array till $ symbol which
INT 21H ;tells the compiler to stop.
MOV CL,0 ;COUNTER 1
MOV SI,0 ;COUNTER 2
GET_CHAR:
MOV AH,1 ;read a character from console and save
INT 21H ;the value entered in variable CHAR in its ASCII form.
MOV AH,0
MOV BL,'Z'
CMP AL,BL
JE REV_PRINT
PUSH AX
INC CL
INC SI
JMP GET_CHAR
PUSH BP ;base pointer: Offset address relative to SS
REV_PRINT:
MOV BP,SP
CMP CL,0
JE ABC_PRINT
MOV DX,[BP]
MOV AH,02h ;display the character that stored in DX.
INT 21H
ADD SP,2
DEC CL
JMP REV_PRINT
ABC_PRINT:
CMP SI,0
JE EXIT
MOV AH,02h ;display the character that stored in DX.
INT 21H
SUB SP,2
MOV BP,SP
MOV DX,[BP]
DEC SI
JMP ABC_PRINT
EXIT:
MOV AH,4CH ;exit to dos or exit to operating system.
INT 21H
CODE ENDS
END START
Final Code after Ped7g helped me:
DATA SEGMENT
MESSAGE DB "ENTER CHARACTER :$"
DATA ENDS
SSEG SEGMENT STACK
DB 100H DUP (?)
SSEG ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:SSEG
START:
MOV AX,DATA
MOV DS,AX
LEA DX,MESSAGE ;print String or Message present in the
MOV AH,9 ;character Array till $ symbol which
INT 21H ;tells the compiler to stop.
MOV CL,0 ;COUNTER 1
MOV SI,0 ;COUNTER 2
GET_CHAR:
MOV AH,1 ;read a character from console and save
INT 21H ;the value entered in AX in its ASCII form.
MOV AH,0
MOV BL,'Z'
CMP AL,BL
JE PREP_TO_PRINT
PUSH AX
INC CL
INC SI
JMP GET_CHAR
PREP_TO_PRINT:
PUSH SI ; store counter
PUSH BP ; base pointer: Offset address relative to SS
MOV BP,SP
ADD BP,4 ; make it point to the last letter (BP+SI stored = 4B)
REV_PRINT:
TEST CL,CL ;until CL is not zero
JE ABC_PRINT
MOV DL,[BP]
MOV AH,02h ;display the character that stored in DL.
INT 21h
ADD BP,2
DEC CL
JMP REV_PRINT
ABC_PRINT:
TEST SI,SI
JE EXIT
SUB BP,2 ; BP was +2 after first character
MOV DL,[BP]
MOV AH,02h ;display the character that stored in DL.
INT 21h
DEC SI
JMP ABC_PRINT
EXIT:
POP BP ; restore BP to original value (just for exercise)
; release all characters from stack (SP += 2*char_counter)
POP SI
SHL SI,1
ADD SP,SI
; here the SP should point to original value from before char input
; you may want to verify these assumptions in debugger,
; to see yourself how the stack works (also open memory view on ss:sp area)
MOV AH,4CH ;exit to dos or exit to operating system.
INT 21H
CODE ENDS
END START
In your reverse printing you do add sp,2
, freeing the stored letter from stack.
While it will technically stay in memory, the next int 21h
(or any interrupt happening meanwhile) will use that stack memory to store return address and other internals, overwriting the old letter.
What you can do is to keep using bp
to address stack (changing bp
in print loop), but keep it also allocated by not freeing the letters until you printed them both ways (not changing sp
meanwhile, only after everything is printed).
Like:
...
JE REV_PRINT
PUSH AX
INC CL
INC SI
JMP GET_CHAR
REV_PRINT:
PUSH SI ; store counter
PUSH BP ; base pointer: Offset address relative to SS
MOV BP,SP
ADD BP,4 ; make it point to the last letter (BP+SI stored = 4B)
REV_LOOP:
TEST CL,CL
JE ABC_PRINT
MOV DL,[BP]
MOV AH,02h ;display the character that stored in DL.
INT 21h
ADD BP,2
DEC CL
JMP REV_LOOP
ABC_PRINT:
TEST SI,SI
JE EXIT
SUB BP,2 ; BP was +2 after first character
MOV DL,[BP]
MOV AH,02h ;display the character that stored in DL.
INT 21h
DEC SI
JMP ABC_PRINT
EXIT:
POP BP ; restore BP to original value (just for exercise)
; release all characters from stack (SP += 2*char_counter)
POP SI
SHL SI,1
ADD SP,SI
; here the SP should point to original value from before char input
; you may want to verify these assumptions in debugger,
; to see yourself how the stack works (also open memory view on ss:sp area)
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.