no stack segment警告为何还在?

  在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

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

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”。然而,编译并连接的结果:
no stack segment警告为何还在?_第2张图片
  学生问我这个事情时,我意识到自己好像也观察到了,却没有顾上理会。
  我将程序用debug装入内存,发现SS的值不对啊!
no stack segment警告为何还在?_第3张图片
  从图中可以看出,装载进内存的程序起始物理地址在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

  编译和连接结果:
no stack segment警告为何还在?_第4张图片
  完美消除warning!
  再debug连接好的可执行文件:
no stack segment警告为何还在?_第5张图片
  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的。眼下先学现在要紧的。

你可能感兴趣的:(no stack segment警告为何还在?)