(汇编 8086) 如何显示堆栈中的一个字母?
(Assembly 8086) How to display a letters from the stack?
我需要编写一个程序,从用户(控制台)获取字母,直到输入字母 '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
在反向打印中,您执行 add sp,2
,从堆栈中释放存储的字母。
虽然技术上它会保留在内存中,但下一个 int 21h
(或同时发生的任何中断)将使用该堆栈内存来存储 return 地址和其他内部信息,覆盖旧字母。
你可以做的是继续使用 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)
...
我需要编写一个程序,从用户(控制台)获取字母,直到输入字母 '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
在反向打印中,您执行 add sp,2
,从堆栈中释放存储的字母。
虽然技术上它会保留在内存中,但下一个 int 21h
(或同时发生的任何中断)将使用该堆栈内存来存储 return 地址和其他内部信息,覆盖旧字母。
你可以做的是继续使用 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)
...