惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 关于现在中小学计算机课的一些想法及思考 2025年度总结
【汇编基础教程】再谈栈
faryou · 2026-01-30 · via

前言

两年前,我写过一篇《【汇编学习随记】汇编中栈的定义》,当时是初次接触汇编语言,对于栈的理解仅限于理解这是一种数据结构,自己却没有理解怎么用栈。当时确实是肤浅了。两年后的今天,我总算是搞清楚了汇编中栈究竟是什么,写下来分享给大家。

栈是什么

数据结构上理解栈,我想不必过多解释了,本质就是一块具有特定进出规则的内存空间,在这块空间内遵循数据先进后出的原则。
但我们作为汇编学习者,仅有这些理解是不够的,让我们从8086CPU的角度看看栈。在8086CPU中,提供了一对段寄存器SS和寄存器SP,用于指向栈顶,CPU对栈的两个操作push(入栈)和pop(出栈)都取决于这两个(段)寄存器,但却没有寄存器能用于标识栈底,这意味着如果我们不提前计算好哪些内存单元是栈空间,栈空间到哪里,那么就很容易出现栈顶超界的问题,可能影响到其他内存空间的数据,从而导致程序异常。(这里也体现了汇编语言和高级语言的不同:汇编语言要求你手动把内存空间抠的很细,但是用高级语言编程时肯定不用考虑这些,因为操作系统已经代为安排好了。想想C++ STL库里的那个栈,根本不用想栈顶是否超界对吧)。对此,我们只能在设计程序时就预留好栈。
因为这一特点,通常情况下,我们不会把栈和代码放在一个段里,而是给栈单独开一个段。
化学上常说,性质决定用途。由于栈这一独特的结构,(至少在汇编中)栈通常用于多层循环时,进入内层循环前暂存外层循环的数据,内层循环结束了再将这些数据恢复出来。这是一个编程时的惯例。

实际应用

上一篇文章中的双层循环就是一个不错的例子,这里就不新出题目了,直接搬过来,要求用栈暂存数据~
编程,将datasg段中每个单词改成小写字母(用栈)

assume cs:codesg,ds:datasg,ss:stacksg

stacksg segment
stacksg ends

datasg segment
  db 'Far             '
  db 'You             '
  db 'HJC             '
  db 'BBS             '
datasg ends

codesg segment
  start:
codesg ends
ends start

直接上答案:

assume cs:codesg,ds:datasg,ss:stacksg;三个段寄存器cs、ds、ss分别关联三个段:代码段、数据段、栈段

stacksg segment
  dw 0,0,0,0,0,0,0,0;定义出16个位,刚刚
stacksg ends

datasg segment
  db 'Far             '
  db 'You             '
  db 'HJC             '
  db 'BBS             '
datasg ends

codesg segment

  start:mov bx,0
        mov cx,4
        mov sp,0;标记当前栈底
        
     s0:push cx;进入内层循环前,cx入栈
        mov si,0
        mov cx,3;重置cx,进内层循环
        
      s:mov al,[bx+si]
        or al,00100000b
        mov [bx+si],al
        inc si
        loop s
        
        add bx,16
        pop cx
        loop s0
        
        mov ax,4c00h
        int 21h
codesg ends
end start