为什么TASM中的程序会在将字符串地址移至BX的那一行崩溃?

问题描述 投票:0回答:1

我在 TASM 中有这个 RPN 计算器程序,可以计算字符串 data_stack 中的表达式:

.model small
.stack 100h

.data
    data_stack db '3 4 +', 0
    top equ 0
    result db 0

.code
start:
    mov ax, @data
    mov ds, ax
    mov bx, offset data_stack
    mov cl, 1
read_argument:
    mov dx, [bx]
    cmp dx, 0
    je calculate_result
    push dx
    inc cl
    inc bx
    jmp read_argument
calculate_result:
    jmp calculate_expression
calculate_expression:
    pop bx
    mov al, [bx]
    cmp al, '+'
    je add_operands
    cmp al, '-'
    je subtract_operands
add_operands:
    pop bx
    add al, [bx]
    jmp calculate_expression
subtract_operands:
    pop bx
    sub al, [bx]
    jmp calculate_expression
print_result:
    mov ah, 02h
    mov dl, al
    int 21h
exit_program:
    mov ah, 4Ch
    int 21h
end start

但是它在调试模式下崩溃了:

mov bx, offset data_stack

我在Dosbox工作,我不知道原因,所以我应该使用另一个寄存器还是什么。

assembly dos tasm dosbox
1个回答
2
投票

我测试了一些 rpn 字符串,调试器显示了良好的结果。 它适用于数字

1 - 9
,结果应在
-128,255
范围内。 字符串中的每个字符均以空格 (20h) 分隔。 我还在 cl 寄存器中添加了
flag
只是为了确保堆栈包含 2 个值。

https://www-stone.ch.cam.ac.uk/documentation/rrf/rpn.html

.model small
.stack 100h

.data
    data_stack db '9 9 + 9 9 * - 8 8 * - 1 -',0 
    ; strings tested
    ; 3 + 4
    ; '3 4 + ', 0
    
    ; 5 * 3 + 9/3 + 9
    ; '5 3 * 9 3 / + 9 + ',0
    
    ; 9 * 2 * 5 + 7 + 8 * 5
    ; '9 2 * 5 * 7 + 8 5 * +',0
    
    ; 9 - 5 * 3 + 7 * 7 + 3 - 8 * 9
    ; '9 5 3 * - 7 7 * + 3 + 8 9 * -',0         
    
    ; 9 + 9 - 9 * 9 - 8 * 8 - 1
    ; '9 9 + 9 9 * - 8 8 * - 1 -',0     
    add_zero db 0
    save_bx dw ?
    result db 0

.code
start:
    mov ax, @data
    mov ds, ax
    
    mov bx, offset data_stack       
    sub bx,2

    mov cl, 0           ; flag, if digits are on the stack
                        ; 0 = no values available, no operation
                        ; 1 = 1 value is on the stack, no operation
                        ; 2+ = more than 2 values are on the stack, operation allowed
    
    xor dx,dx
    
read_argument:  
    add bx,2
    
    mov dl, [bx]        ; ASCII code for '1' - '9' = 31h - 39h
                        ; '*' = 2ah 
                        ; '/' = 2fh
                        ; '+' = 2bh
                        ; '-' = 2dh
    
    cmp dl,0            ; end of string
    jz print_result
    
    check_sign:
        cmp dl, 2fh     
        ja check_1
        
    check_values_on_stack:
        cmp cl, 2       ; 2 values are on the stack, so we can do arithmetic operation
        jae arithmetic_operation
        jmp no_operation
        
    check_1:
        cmp dx, 31h     ; ok if >= 1 
        jb check_next_value     
    
    check_9:
        cmp dx, 39h     ; ok if <= 9 
        ja check_next_value
    
        inc cl
        
    value_ok:       
        sub dl,30h      ; we want digits 1 - 9 not ASCII values of '1' - '9'
        push dx         ; save digit on stack

        jmp check_next_value

    no_operation:
        xor cl,cl       ; reset flag

    check_next_value:       
        jmp read_argument

    arithmetic_operation:
        mov [save_bx], bx   ; save address of element in string
    
        pop bx              ; pop digits
        pop ax          
        
        cmp dl,2ah          ; mul
        jz mul_op
        cmp dl,2fh          ; div
        jz div_op
        cmp dl,2bh          ; add
        jz add_op
        cmp dl,2dh          ; sub
        jz sub_op
        
        
        mul_op:
            mul bl
            push ax
            dec cl      ; after operation one value is on the stack
            jmp restore_bx
            
        div_op:
            div bl
            push ax
            dec cl      ; after operation one value is on the stack
            jmp restore_bx
            
        add_op:
            add al,bl
            push ax
            dec cl      ; after operation one value is on the stack
            jmp restore_bx
            
        sub_op:
            sub al,bl
            push ax
            dec cl      ; after operation one value is on the stack
            ;jmp restore_bx
            
        restore_bx:
            mov bx, [save_bx]   ; save address of element in string
            mov [result],al
            jmp check_next_value
            

print_result:
    mov ah, 02h
    mov dl, [result]            ; show ASCII char equal to result
    int 21h
    
exit_program:
    mov ah, 4Ch
    int 21h
end start
© www.soinside.com 2019 - 2024. All rights reserved.