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 调用)也很合理。
我正在尝试编写一个简单的 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 调用)也很合理。