You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编子程序推送结果至栈后无法返回的问题及开发需求咨询

8086汇编子程序问题修复与需求实现

核心问题分析

  1. 代码段数据错误:子程序my_subroutine中直接在代码段定义local1-local5变量,执行流会将这些数据当作指令执行,导致程序异常。
  2. 栈平衡破坏:主程序预先push 3个占位值用于接收返回结果,原代码子程序额外push结果而非替换栈上的占位值,导致返回地址被覆盖,ret时跳转到错误位置,引发无限循环。
  3. 寄存器恢复顺序错误:栈是后进先出结构,保存寄存器顺序为ax->bx->si->di->cx,恢复时需按cx->di->si->bx->ax顺序pop,原代码恢复顺序错误导致寄存器值混乱。

修正后的完整代码

org 0x0100      
jmp start  

; 1. 输入变量:学号后四位3440
input1: db 3  
input2: db 4  
input3: db 4  
input4: db 0  
message1: db 'The value of AX, BX and CX is: '
length: dw 31

start:
    ; 推送3个占位值,用于接收子程序返回结果
    push 0       ; 占位1:对应CX
    push 0       ; 占位2:对应BX
    push 0       ; 占位3:对应AX

    call my_subroutine

    ; 弹出结果到AX、BX、CX(注意栈顺序:先弹CX,再BX,最后AX)
    pop cx       
    pop bx       
    pop ax       

    ; 显示最终结果
    call display
    
    ; 退出程序
    mov ax, 0x4c00
    int 0x21

my_subroutine:
    push bp
    mov bp, sp
    ; 2. 保存寄存器:AX、BX、SI、DI、CX
    push ax
    push bx
    push si
    push di
    push cx

    ; 3. 栈分配5个局部变量(每个dw占2字节,共10字节),初始化为1-10的随机值
    sub sp, 10
    mov word [bp-2], 1    ; local1 = 1
    mov word [bp-4], 3    ; local2 = 3
    mov word [bp-6], 5    ; local3 = 5
    mov word [bp-8], 7    ; local4 = 7
    mov word [bp-10], 9   ; local5 = 9

    ; 示例运算逻辑:使用输入变量和局部变量计算结果
    ; 计算AX结果:input1 + input2 + local1
    mov ax, [input1]
    add al, [input2]
    add ax, [bp-2]
    ; 将结果写入栈上的AX占位位置(bp+6:bp是栈底,+4是返回地址,+6是第一个push的AX占位)
    mov [bp+6], ax

    ; 计算BX结果:input3 * local2 - input4
    mov bx, [input3]
    mul byte [bp-4]
    sub ax, [input4]
    mov bx, ax
    ; 将结果写入栈上的BX占位位置(bp+8)
    mov [bp+8], bx

    ; 计算CX结果:local3 + local4 + local5
    mov cx, [bp-6]
    add cx, [bp-8]
    add cx, [bp-10]
    ; 将结果写入栈上的CX占位位置(bp+10)
    mov [bp+10], cx

    ; 释放局部变量占用的栈空间
    add sp, 10
    ; 恢复寄存器(后进先出顺序)
    pop cx
    pop di
    pop si
    pop bx
    pop ax
    pop bp
    ret              ; 返回主程序,栈平衡已维护

cls:
  push es
  push ax
  push di

  mov ax, 0xB800
  mov es, ax
  mov di, 0

allSpace:
 mov word [es:di], 0x0720
 add di, 2
 cmp di, 4000
 jne allSpace

 pop di
 pop ax
 pop es
 ret

convert_num_to_string:
    push bp
    mov bp, sp 
    push es
    pusha
    mov ax, 0xb800
    mov es, ax
    mov ax, [bp+4]
    mov bx, 10
    mov cx, 0

nextdigit: 
    mov dx, 0
    div bx
    add dl, 0x30
    push dx
    inc cx
    cmp ax, 0
    jnz nextdigit

nextpos: 
    pop dx
    mov dh, 0x07
    mov [es:di], dx
    add di, 2
    loop nextpos

    popa
    pop es
    pop bp
    ret 2

display_message:
  push bp
  mov bp, sp
  push es
  push ax
  push bx
  push cx

  mov ax, 0xb800
  mov es, ax

  mov si, [bp+6]
  mov cx, [bp+4]
  mov ah, 0x07

printAllChar:
  mov al, [si]
  mov [es:di], ax
  add di, 2
  add si, 1
  loop printAllChar

  pop cx
  pop bx
  pop ax
  pop es
  pop bp
  ret 4

display:  
    call cls
    mov di, 0                  
    push message1                  
    push word [length]
    call display_message
    
    mov di, 62 
    push ax           
    call convert_num_to_string

    mov di, 66
    push bx           
    call convert_num_to_string

    mov di, 70
    push cx           
    call convert_num_to_string

    ret

需求实现说明

  • 输入变量:采用学号后四位3440,定义为input1-input4四个字节变量。
  • 返回值处理:主程序预先push 3个占位值,子程序通过栈偏移(bp+6、bp+8、bp+10)直接修改栈上的占位值,主程序pop即可获取结果,避免栈平衡破坏。
  • 局部变量:通过栈分配5个双字局部变量,初始化为1、3、5、7、9(1-10范围内的随机值),使用后释放栈空间。
  • 寄存器保护:子程序开头push需要使用的寄存器,结尾按相反顺序pop恢复,保证主程序寄存器不受影响。
  • 结果显示:复用原有的display相关子程序,将AX、BX、CX的值输出到控制台。

内容的提问来源于stack exchange,提问作者Fatima sami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:55:23