程序说明:编制一个子程序把一个16位二进制用十六进制形式在屏幕上显示出来,采用堆栈方法传递这个16位二进制数,并用一个主程序验证它。
代码如下:
; 数据段
DSEG SEGMENT ;定义数据段
STRING DB 0DH,0AH, "Hex output : ",0DH,0AH, "$ "
DSEG ENDS
; 堆栈段
SSEG SEGMENT STACK ;定义堆栈段
DB 100H DUP(?) ;设置堆栈段大小为100H
SSEG ENDS
; 代码段
CSEG SEGMENT ;定义代码段
ASSUME CS:CSEG, DS:DSEG, SS:SSEG ;关联段寄存器
START: ;主程序入口点
MAIN PROC
MOV AX,DSEG
MOV DS,AX
MOV CH,2
MOV BX,1111000010100101B ;16进制为F0A5
PUSH BX
CALL BTOH
ADD SP,4
MOV CL,8
ROL BX,CL
PUSH BX
CALL BTOH
CALL EXIT
MAIN endp
BTOH PROC
PUSH BP
PUSH CX
PUSH BX
MOV CH,2
MOV BP,SP
MOV BL,BYTE PTR[BP+4]
AGAIN:
MOV CL,4
ROL BL,CL
MOV AL,BL
AND AL,0FH
OR AL,30H
CMP AL,3AH
JB NEXT
ADD AL,07H
NEXT:
MOV DL,AL
MOV AH,2
INT 21H
DEC CH
JNZ AGAIN
POP BX
POP CX
POP BP
ret
BTOH endp
; 退出 DOS
EXIT:
MOV AH,1
INT 21H
MOV AX, 4C00H ;返回DOS系统
INT 21H
CSEG ENDS
END START ; 程序结束
问题在于结果不是F0A5。
初步怀疑是堆栈传递参数,但仍未解决,请各位指点一下。
谢谢!
------解决方案--------------------------------------------------------
MOV BP,SP 应该放在紧接 push bp 指令后吧. 堆栈分析很简单的, 因为这时:
[bp][0]: 刚才压栈的 bp
[bp][2]: 子程返回地址. 如果子程是 far 类型的话, 这里要占用两个 word 以存放 cs:ip
[bp][4]: 调用子程前压栈的参数
如果 mov bp, sp 指令放在了 push cx 和 push bx 指令之后的话, 堆栈就成了:
[bp][0]: 刚才压栈的 bx
[bp][2]: 刚才压栈的 cx
[bp][4]: 子程开始时压栈的 bp
[bp][6]: 子程返回地址
[bp][8]: 这里才识调用子程前压栈的参数