汇编语言堆栈和子例程

时间:2011-12-13 07:49:44

标签: 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 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分解,以便我可以跟进并希望将其应用于另一个审核问题。

2 个答案:

答案 0 :(得分:3)

每次推送都会按推送元素的大小递减sp。每个流行音乐同样增加sp

所以,你从sp = 100h开始,然后是

  1. 使用push ax
  2. 减去2
  3. 使用push ax
  4. 减去2
  5. call subr减去2,因为调用会推送返回地址,而这里是16位
  6. 使用push bp减去2并到达sp = 0F8h
  7. 使用pop bp
  8. 添加2
  9. 使用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。