我真的很困惑堆栈指针和字节指针是如何工作的。以下是问题所引用的代码段:
.data
v1 db 'AB'
v2 db 'CD'
v3 db 'EF
.code
start:
mov ax,@data
mov ds,ax
mov sp,0100h
;call the subroutine
mov ax,offset v1
push ax
mov ax,offset v2
push ax
call subr
retsub:
子程序是:
subr:
push bp
mov bp,sp
mov si,[bp+6]
add si,1
mov dl,[si]
mov ah,2
int 21h
pop bp
ret
与此问题相关的三个评论问题有以下答案:
1.在子程序中mov bp,sp
之后,bp
中十六进制值的值为00F8
。
2.子程序将单个ASCII字符写入标准输出。它写B
3.子程序在sp
标签处的指令返回主程序后,retsub
寄存器中的十六进制值为00FC
。
任何人都可以引导我完成这些步骤,以便我能更好地理解这个过程吗?
我的偏移数据表是:
offset 00 01 02 03 04 05
data 41 42 43 44 45 46
我在脑海中解决这个问题的方式是:
mov sp,0100h ;sp = 0100
mov ax,offset v1 ;ax = 4142
push ax ;4142 is pushed onto the stack
mov ax,offset v2 ;ax = 4344
push ax ;4344 is pushed onto the stack
call subr
stack
------
|4344|
------
|4142|
------
据我所知,我确信我甚至没有做到这一点。如果可以,请将每个步骤的bp和sp分解,以便我可以跟进并希望将其应用于另一个审核问题。
答案 0 :(得分:3)
每次推送都会按推送元素的大小递减sp
。每个流行音乐同样增加sp
。
所以,你从sp
= 100h开始,然后是
push ax
push ax
call subr
减去2,因为调用会推送返回地址,而这里是16位push bp
减去2并到达sp
= 0F8h pop bp
ret
添加2并删除16位返回地址并到达sp
= 0FCh 答案 1 :(得分:1)
在子程序中移动bp,sp之后,bp中十六进制值的值为00F8
是的,因为sp用100h初始化,然后推送两个字大小的参数(push ax),调用子程序将2字节的返回地址压入堆栈,最后执行bp执行,减少sp与另一个2个字节。所以我们有100h-2-2-2-2 = 00F8h。堆栈在Intel CPU上的内存中向下增长。
子程序在标签retsub的指令处返回主程序后,sp寄存器中的十六进制值为00FC。
这是因为子程序以“pop bp”指令退出,然后是从堆栈中弹出(读取并增加sp)返回地址的ret指令。所以00F8 + 2 + 2 = 00FC。