我需要编写一个程序来获取用户(控制台)的信件,直到输入字母'Z'(例如:ABCZ)。字母必须放在堆栈上。完成输入后,程序应以相反的顺序打印堆栈中的字母(例如:CBA),然后再按字母顺序打印堆栈中的字母(例如:ABC)。我编写了程序,但最后一部分工作不正确。除第一个字母外,程序不按字母顺序显示堆栈中的字母。我想以相反的顺序显示它后继续使用SP。
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
Ped7g之后的最终密码帮助了我:
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
答案 0 :(得分:1)
在反向打印中,执行add sp,2
,从堆栈中释放存储的字母。
虽然它在技术上会留在内存中,但下一个int 21h
(或同时发生的任何中断)将使用该堆栈内存来存储返回地址和其他内部,覆盖旧信。
你可以做的是继续使用bp
来解决堆栈(在打印循环中更改bp
),但保持它也是通过不释放字母来分配,直到你双向打印它们(不改变sp
同时,只有在打印完所有内容之后。)
像:
...
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)
...