【问题标题】:PUSH To a FULL Stack 8086 Assembly推入全栈 8086 组件
【发布时间】:2016-01-02 07:17:10
【问题描述】:

PUSH 到 FULL 堆栈的物理后果是什么 令人惊讶的是,当只为堆栈分配 2 个字节 [1 个字] 并 PUSH 三个字然后将它们弹出到不同的寄存器中时,它没有任何错误地完成 推送第二个项目时,我能对堆栈内容说些什么

这是堆栈段定义:

Stack_segment_name segment para stack
db 2 dup(0) ;define your stack segment
Stack_segment_name ends

代码如下:

Code_segment_name segment
Main_prog PROC FAR

assume     SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name,ES:Data_segment_name

MOV AX,Data_segment_name ; load the starting address of the data
MOV DS,AX ; segment into DS reg.

MOV AX,1715H
MOV BX,1518H
MOV CX,2944H
PUSH AX
PUSH BX
PUSH CX
POP SI 
POP DI  
POP DX



MOV AH,4CH
INT 21H


Main_prog endp
Code_segment_name ends
    end Main_prog

执行代码后:

SI=2944H
DI=1518H
DX=1715H

【问题讨论】:

  • 8086 上的堆栈段(如 8086 上的所有段)为 64K。 SP(堆栈指针)是一个 16 位寄存器,因此如果/当您超过 64K 堆栈时,它会回绕。
  • 好的,它会环绕,但这与实际程序的堆栈段定义中声明的 2 字节大小冲突。
  • 汇编器中堆栈的大小不会转换为内存中相同的固定大小。所有物理段的大小都是 64k。您指定的大小是最小保证之前的字节数堆栈包装。因此,如果您指定一个包含 2 个字节的堆栈,则 SS 将自动设置为内存中 2 个字节所在段落的开头。 SP 将设置为堆栈的大小 - 在您的情况 2 中。因此,您最终会得到类似 SS:0002h 作为起始堆栈位置的东西。您推送的第一个单词将位于 SS:0000h,您推送的第二个单词将换行并放置在 SS:0fffeh
  • 而我的cmets是在8086实模式下的。
  • 我不认为你运行了你认为你运行的实验。我看不到您如何将堆栈指针设置为您声明的堆栈区域。我认为您的程序正在使用加载程序提供的堆栈区域运行,该堆栈区域通常很大。 (如果您确实将 SP 设置为您定义的区域,您的推送将覆盖超出其末尾的一些字节。如果这些字节对某些内容至关重要,您的程序将失败。如果不是,它将意外成功,这回答了您的原始问题)。见stackoverflow.com/a/34546569/120163

标签: assembly x86-16 callstack


【解决方案1】:

您在程序中声明的堆栈与 CPU 看到堆栈的方式不同。

在 8086 上,CPU 将从线性地址 SS*16 开始的 64KB 内存块视为堆栈。

当您声明一个只有 2 个字节的堆栈时,第一个 push 到达您期望的位置,但此后堆栈指针 SP 为 0。因此,下一个 push 减去 2(给出 0xFFFE)并将其操作数存储在记忆。第三个push 也是如此。由于没有内存冲突,一切似乎都很好......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多