tasm中的自动代码插入

Automatic code insertion in tasm

我正在尝试编写一个简单的 C 启动程序来生成 DOS COM 文件。 我还没有写 argc,argv 实现。 作为测试,我试图放置虚拟 argv[0] 和 argc=1。 但是我在转储中得到了 2 条意想不到的行:

;---------------------------------------------------------------

Turbo Debugger Log

CPU 80486

  cs:0100B85902          mov    ax,0259                      
  cs:0103 50             push   ax                           
  cs:0104 BF5002         mov    di,0250                      
  cs:0107 FF35           push   word ptr [di]                
  cs:0109 90             nop                   ; << Unexpected 1              
  cs:010A 0E             push   cs             ; << Unexpected 2               
  cs:010B E83C00         call   014A                         
  cs:010E E80000         call   0111                         
  cs:0111 B44C           mov    ah,4C                        
  cs:0113 CD21           int    21                           
  cs:0115 55             push   bp                           
  cs:0116 8BEC           mov    bp,sp                        
  cs:0118 8B4604         mov    ax,[bp+04]                   
  cs:011B 50             push   ax                           
  cs:011C B40E           mov    ah,0E                        
  cs:011E CD10           int    10                           
  cs:0120 58             pop    ax                           
  cs:0121 5D             pop    bp                           
  cs:0122 C3             ret                                 
  cs:0123 50             push   ax                           
  cs:0124 55             push   bp                           
  cs:0125 8BEC           mov    bp,sp                        
  cs:0127 C746026900     mov    word ptr [bp+02],0069        
  cs:012C 5D             pop    bp                           
  cs:012D E8E5FF         call   0115                         
  cs:0130 59             pop    cx                           
  cs:0131 C3             ret                                 
  cs:0132 55             push   bp                           
  cs:0133 8BEC           mov    bp,sp                        
  cs:0135 56             push   si                           
  cs:0136 33F6           xor    si,si                        
  cs:0138 EB01           jmp    013B                         
  cs:013A 46             inc    si                           
  cs:013B 8B5E04         mov    bx,[bp+04]  

Terminated, exit code 7

Stack :

5B7C:0028 FFFF  
5B7C:0026 FFFF  
5B7C:0024 FFFF  
5B7C:0022 FFFF  
5B7C:0020 FFFF  
5B7C:001E FFFF  
5B7C:001C FFFF  
5B7C:001A FFFF  
5B7C:0018 FFFF  
5B7C:0016 0DEE  
5B7C:0014 1C80  
5B7C:0012 0280  
5B7C:0010 2225  
5B7C:000E 01AE  
5B7C:000C 2225  
5B7C:000A 01E4  
5B7C:0008 F01D  
5B7C:0006 FEF0  
5B7C:0004 9A00  
5B7C:0002 9FFF  
5B7C:0000 20CD  
5B7C:FFFE 0000  
5B7C:FFFC 0259  ; << argv

5B7C:FFFA 0001  ; << argc  

5B7C:FFF8 5B7C  ; << Unexpected CS

5B7C:FFF6 0111  
5B7C:FFF4 3206  
5B7C:FFF2 5B7C  
5B7C:FFF0 0115  
5B7C:FFEE 3206  

;---------------------------------------------------------------

我不明白为什么这些行是由汇编程序添加的。 段填充可能是原因吗?另外,是否可以有一个堆栈框架 'like' 构造? 请赐教。 这是来源:

;---------------------------------------------------------------
_TEXT   SEGMENT WORD PUBLIC USE16 'CODE'
_TEXT   ENDS
_DATA   SEGMENT WORD PUBLIC USE16 'DATA'
_DATA   ENDS
DGROUP  GROUP   _DATA , _TEXT



_TEXT   SEGMENT
    assume  cs: _TEXT, ds: _DATA, ss: nothing, es: nothing


    ORG 0100h

;----------------------------------
; Program Starts Here...
;----------------------------------
start:

    ; Push arguments in reverse order...
    ;====================================

    mov ax, offset DGROUP:argv
    push    ax

    mov di, offset DGROUP:argc
    push    word ptr [di]

    call    far ptr _main
    call near ptr __terminate

;----------------------------------


;----------------------------------
; Function Declarations...
;----------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__terminate     proc    DIST
    PUBLIC  __terminate
    mov ah, 4ch
    int 21h
__terminate     endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;----------------------------------

_TEXT   ends

_DATA   SEGMENT


argc    dw  1
arg0    db  'NEW_C0', 0h
argv    dw  DGROUP:arg0

_DATA   ENDS

    extrn   _main

end start
;---------------------------------------------------------------

来自我找到的标题为 "Turbo Assembler 2.0 New Features":

的文档

The default condition is SMART enabled. When SMART is enabled, a qualifying FAR jump will be replaced by a NEAR or a SHORT jump. Also, when SMART is enabled, a qualifying FAR call will be replaced by a PUSH CS instruction and a NEAR call.

所以 TASM 很聪明地认识到 _main 和您的启动代码在同一段(毕竟您正在生成一个 COM 文件),冒昧地替换:

call    far ptr _main

通过更短更快的 near call:

push    cs
call    _main

push 是必需的,因为 TASM 必须假定 main 本身是用 far return 编译的;它需要堆栈上的 32 位 return 地址。

您应该问问自己,您是否真的 want/need 在 COM 文件中进行了如此远的调用。

至于nop,我就不知道了。这可能是为了使 far return 更有效率而进行的文字填充,但我发现 Jester 的解释(保留 space 用于真正的 far 调用)也很合理。