【问题标题】:(Assembly 8086) How to display a letters from the stack?(Assembly 8086) 如何显示堆栈中的字母?
【发布时间】:2018-07-03 03:30:19
【问题描述】:

我需要编写一个程序,该程序会从用户(控制台)获取字母,直到输入字母“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

【问题讨论】:

    标签: assembly stack x86-16


    【解决方案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)
            ...
    

    【讨论】:

    • @IgorOsipov 您可能想要“接受”答案(在答案顶部附近的左侧),以使这个问题在视觉上对其他人“回答”(有用),并增加我的声誉点(很好)——如果你觉得它足够好的话。
    • 当然!我只是想完全发布你的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2021-08-14
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    相关资源
    最近更新 更多