no stack segment警告为何还在?

简介:   在8086汇编中,在masm5.0下link的时候出现warning L4021: no stack segment是习以为常的现象。   如,针对下面的程序:assume cs:codesg,ds:datasgdatasg segment dw 1,2,3,4,5datasg endscodesg segmentstart: mov ax, da

  在8086汇编中,在masm5.0下link的时候出现warning L4021: no stack segment是习以为常的现象。
  如,针对下面的程序:

assume cs:codesg,ds:datasg
datasg segment
    dw 1,2,3,4,5
datasg ends

codesg segment
start: mov ax, datasg
       mov ds, ax
       mov bx, 0

       mov ax,4c00h
       int 21h
codesg ends

end start

  编译和连接的结果是:
这里写图片描述
  对此的解释是:程序中没有安排堆栈段。这个警告可以忽略,程序能够运行,并且得到正确的结果。
  好吧!那在在程序中加上栈段,警告就该没有了吧?
  写下面的程序:

assume cs:codesg,ds:datasg, ss:stacksg
datasg segment
    dw 1,2,3,4,5
datasg ends

stacksg segment
      dw  0,0,0,0,0,0,0,0
stacksg ends

codesg segment
start: mov ax, stacksg
       mov ss, ax
       mov sp, 16
       mov ax, datasg
       mov ds, ax
       mov bx, 0

       mov ax,4c00h
       int 21h
codesg ends
end start

  程序中,定义了“stacksg segment”,也assume了“ss:stacksg”。然而,编译并连接的结果:
这里写图片描述
  学生问我这个事情时,我意识到自己好像也观察到了,却没有顾上理会。
  我将程序用debug装入内存,发现SS的值不对啊!
这里写图片描述
  从图中可以看出,装载进内存的程序起始物理地址在075A0H(DS=075AH),跨过100H的程序段前缀PSP,datasg段该开始于076A0。这一段尽管只有10个字节,但由于下面的stacksg的段起始地址应该是16(10H)的倍数,stacksg段的起始地址该是076B0H才对。然则,SS的值是0769H纯粹没有道理。
  只能说明一个事实,人家没有把村长当干部!在连接过程中,并未因为有“stacksg segment”,和assume了“ss:stacksg”就认为设置了堆栈段。
  怎样做才能被承认呢?
  找度娘,说是将段定义写成下面的形式:

stacksg segment stack
      ……
stacksg ends

  按指点修改程序,写为:

assume cs:codesg,ds:datasg, ss:stacksg
datasg segment
    dw 1,2,3,4,5
datasg ends

stacksg segment stack
      dw  0,0,0,0,0,0,0,0
stacksg ends

codesg segment
start: mov ax, stacksg
       mov ss, ax
       mov sp, 16
       mov ax, datasg
       mov ds, ax
       mov bx, 0

       mov ax,4c00h
       int 21h
codesg ends
end start

  编译和连接结果:
这里写图片描述
  完美消除warning!
  再debug连接好的可执行文件:
这里写图片描述
  SS=076BH是对的!居然还有SP=0010H!这是在还没有执行程序中任何指令的情况下发生的事情!是连接程序自动地发现定义的堆栈段大小就是10H!
  那,这是为什么呢?
  查阅汇编程序中段的定义语法,完整的是:

segname SEGMENT [align_type][combine_type][user_type]['class']
...
segname ENDS

  其中的组合类型(combine_type)可以是:

  • PUBLIC:该段连接时将与有相同名字的其他分段连接在一起,其连接次序由连接命令指定。
  • COMMON:该段在连接时与其他同名分段有相同的起始地址,所以会产生覆盖。
  • AT expression: 使段的起始地址是表达式所计算出来的16位段地址,但它不能用来指定代码段。
  • STACK:指定该段在运行时为堆栈段的一部分。

      这些选项的含义不解释了。要解释通可能还需要再补充不少其他知识。我们先明白,stacksg segment stack中最后的stack让连接程序将定义的堆栈段当堆栈段用了。
      最后多说一句是,要真正说清楚这件事,得谈多个.obj是如何link为一个.exe的。眼下先学现在要紧的。

目录
相关文章
GEE:如何批量处理并下载指定时间范围的月尺度NDVI数据集(MOD09GA为例)
GEE:如何批量处理并下载指定时间范围的月尺度NDVI数据集(MOD09GA为例)
1070 0
|
运维 Kubernetes 监控
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
4012 0
|
4月前
|
存储 设计模式 Java
Java 期末考试不挂科必背基础知识点复习笔记整理
这是一份全面的Java基础知识点复习笔记,涵盖核心特性、数据类型、流程控制、数组、异常处理、JVM原理、多线程、设计模式及Java 8+新特性等内容。结合买飞机票、验证码生成和评委打分等应用实例,助你掌握考试重点,轻松应对Java期末考试,避免挂科!附带代码资源,供深入学习使用。链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)
104 0
|
关系型数据库 MySQL 数据库
Navicat备份数据库
涵盖`Navicat`数据库备份、数据安全及备份策略等主题。文库采用精美主题,提升阅读体验。
257 1
Navicat备份数据库
|
应用服务中间件 uml
【UML】软件工程中常用图:类图、部署图、时序图、状态图
【UML】软件工程中常用图:类图、部署图、时序图、状态图
2710 1
|
JSON 关系型数据库 MySQL
MySQL 8.0常用函数汇总与应用实例
这些函数只是MySQL 8.0提供的众多强大功能的一部分。通过结合使用这些函数,你可以有效地处理各种数据,优化数据库查询,并提高应用程序的性能和效率。
313 3
|
11月前
|
网络协议 算法 数据库
OSPF协议详解:工作原理与实现机制
OSPF协议详解:工作原理与实现机制
997 0
|
负载均衡 监控 微服务
手把手教你搭建SpringCloud项目(三)集成Eureka服务注册中心
手把手教你搭建SpringCloud项目(三)集成Eureka服务注册中心
706 0
|
Python
pyqt 界面卡顿 解决办法 多线程
pyqt 界面卡顿 解决办法 多线程
371 0
|
消息中间件 Kafka API
这些年背过的面试题——Kafka篇
本文是技术人面试系列Kafka篇,面试中关于Kafka都需要了解哪些基础?一文带你详细了解,欢迎收藏!