【发布时间】:2017-01-19 15:28:31
【问题描述】:
我对汇编语言有点陌生,想了解它在旧系统上的工作原理。我知道大内存模型使用远指针,而小内存模型使用近指针,并且大模型中的返回地址是 4 个字节而不是两个,所以第一个参数从 [bp+4] 更改为 [bp+6]。但是,在将图形库从小模型适配到大模型的过程中,还有其他一些我似乎不明白的细微之处。从 C 中使用大内存模型运行此代码应该会清除屏幕,但它会挂起系统(它是用 TASM 组装的):
; void gr256cls( int color , int page );
COLOR equ [bp+6]
GPAGE equ [bp+8]
.MODEL LARGE,C
.186
public C gr256cls
.code
gr256cls PROC
push bp
mov bp,sp
push di
pushf
jmp skip_1
.386
mov ax,0A800h
mov es,ax
mov ax,0E000h
mov fs,ax
CLD
mov al,es:[bp+6]
mov ah,al
mov bx,ax
shl eax,16
mov ax,bx
cmp word ptr GPAGE,0
je short cls0
cmp word ptr GPAGE,2
je short cls0
jmp short skip_0
cls0:
mov bh,0
mov bl,1
call grph_cls256
skip_0:
cmp word ptr GPAGE,1
je short cls1
cmp word ptr GPAGE,2
je short cls1
jmp short skip_1
cls1:
mov bh,8
mov bl,9
call grph_cls256
skip_1:
.186
popf
pop di
pop bp
ret
.386
grph_cls256:
mov fs:[0004h],bh
mov fs:[0006h],bl
mov cx,16384
mov di,0
rep stosd
add word ptr fs:[0004h],2
add word ptr fs:[0006h],2
mov cx,16384
mov di,0
rep stosd
add word ptr fs:[0004h],2
add word ptr fs:[0006h],2
mov cx,16384
mov di,0
rep stosd
add word ptr fs:[0004h],2
add word ptr fs:[0006h],2
mov cx,14848 ;=8192+6656
mov di,0
rep stosd
;; Freezes here.
ret
gr256cls ENDP
end
它挂在grph_256cls 末尾的ret。事实上,即使我从函数的开头立即ret,它仍然会在之后挂起。在两种模式下编码汇编时是否有完整的差异列表,以便我更容易理解发生了什么?
编辑:澄清一下,这是原始来源。这不是生成的输出;它旨在组装并链接到库中。
【问题讨论】:
-
请注意,在大代码模型中,函数调用将一个四字节的返回地址压入堆栈。您可能希望在
COLOR和GPAGE的定义中考虑这一点。 -
参数原来是
[bp+4]和[bp+6],两个字节的返回地址压栈,所以我给每个增加了两个字节。 -
您需要展示完整的代码以及构建和运行它所采取的所有步骤,以便我们重现问题。如有必要,将调用此函数的 C 代码减少到重现问题所需的最低限度。使您帖子中的代码与您使用的代码完全相同。
-
只是猜测:在大型模型中,TASM 可能需要明确的
retf。 -
我将它们全部替换为
retfs,但并没有什么不同。但是我确实发现,如果我完全跳过grph_cls256,就不会发生崩溃。