Pointers 汇编语言栈和子程序
对于堆栈指针和字节指针是如何工作的,我真的很困惑。以下是问题所引用的代码段:Pointers 汇编语言栈和子程序,pointers,assembly,stack,byte,Pointers,Assembly,Stack,Byte,对于堆栈指针和字节指针是如何工作的,我真的很困惑。以下是问题所引用的代码段: .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
.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在每个步骤中的作用,这样我就可以跟进,并希望能将其应用到另一个复习问题上
在子程序中mov bp、sp之后,bp中十六进制值的值为00F8
是的,因为sp是用100h初始化的,所以会推送两个字大小的参数(推送ax),调用子例程,将2字节的返回地址推送到堆栈上,并执行最后一次推送bp,将sp再减少2字节。所以我们有100h-2-2-2-2=00F8h。堆栈在英特尔CPU上的内存中向下增长
在子例程返回到主程序的标签retsub处的指令后,sp寄存器中的十六进制值为00FC
这是因为子程序退出时带有一条“pop bp”指令,然后是一条ret指令,该指令从堆栈中弹出(从sp读取并增加sp)一个返回地址。所以00F8+2+2=00FC
在子程序中mov bp、sp之后,bp中十六进制值的值为00F8
是的,因为sp是用100h初始化的,所以会推送两个字大小的参数(推送ax),调用子例程,将2字节的返回地址推送到堆栈上,并执行最后一次推送bp,将sp再减少2字节。所以我们有100h-2-2-2-2=00F8h。堆栈在英特尔CPU上的内存中向下增长
在子例程返回到主程序的标签retsub处的指令后,sp寄存器中的十六进制值为00FC
这是因为子程序退出时带有一条“pop bp”指令,然后是一条ret指令,该指令从堆栈中弹出(从sp读取并增加sp)一个返回地址。因此,00F8+2+2=00FC。每次推压都会根据推压元件的大小减小
sp
。每个pop的增量sp
类似
所以,你从sp
=100h开始,然后
push ax减去2
push ax减去2
call subr
减去2,因为call推送返回地址,这里是16位按下bp
减去2,得出sp
=0F8hpop bp
ret
添加2,删除16位返回地址,并到达sp
=0FCh每次推送都会按推送元素的大小递减
sp
。每个pop的增量sp
类似
所以,你从sp
=100h开始,然后
push ax减去2
push ax减去2
call subr
减去2,因为call推送返回地址,这里是16位按下bp
减去2,得出sp
=0F8hpop bp
ret
添加2,删除16位返回地址,并到达sp
=0FCh我在任何地方都看不到
FAR
关键字(既不在call
指令中,也不在ret
指令中,也没有PROC
),因此返回地址为2字节长。其他2个字节来自推送bp。Alex,你是对的。我回答得太快,没有正确地想清楚。我已经编辑了我的答案和你的+1。谢谢,我想我理解堆栈的递增/递减。我仍然对间接寻址有点迷茫,无法完全理解代码的内容。我在任何地方都看不到FAR
关键字(既不在call
指令中,也不在ret
指令中,也没有PROC
),因此返回地址为2字节长。其他2个字节来自推送bp。Alex,你是对的。我回答得太快,没有正确地想清楚。我已经编辑了我的答案和你的+1。谢谢,我想我理解堆栈的递增/递减。我仍然对间接寻址有点迷茫,无法完全理解代码以了解它打印的内容。顺便说一句,您不需要在.COM和.EXE程序开始时显式加载SS
或SP
。DOS负责加载SS:SP
。此外,应该使用适当的堆栈段定义或特殊关键字(如果汇编程序支持任何关键字)设置堆栈大小。ESP不应加载任意硬编码值,必须为堆栈保留空间。顺便说一句,您不需要在.COM和.EXE程序的开头显式加载SS
或SP
。DOS负责加载SS:SP
。此外,应该使用适当的堆栈段定义或特殊关键字(如果汇编程序支持任何关键字)设置堆栈大小。ESP不应加载任意硬编码值,必须为堆栈保留空间。谢谢,这对我来说是有意义的。谢谢,这对我来说是有意义的。