汇编子程序推送结果至栈后无法返回的问题及开发需求咨询
8086汇编子程序问题修复与需求实现
核心问题分析
- 代码段数据错误:子程序
my_subroutine中直接在代码段定义local1-local5变量,执行流会将这些数据当作指令执行,导致程序异常。 - 栈平衡破坏:主程序预先push 3个占位值用于接收返回结果,原代码子程序额外push结果而非替换栈上的占位值,导致返回地址被覆盖,
ret时跳转到错误位置,引发无限循环。 - 寄存器恢复顺序错误:栈是后进先出结构,保存寄存器顺序为
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
相关产品推荐
相关产品推荐

