如何将针对小内存模型的 DOS 程序集转换为大内存模型?
How do I translate DOS assembly targeted for the small memory model to the large memory model?
我对汇编语言有些陌生,想了解它在旧系统上的工作原理。我了解到大内存模型使用远指针而小内存模型使用近指针,并且大模型中的 return 地址是 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
它仍然会立即挂起。在两种模式下编写汇编代码时是否有完整的差异列表,以便我更容易理解发生了什么?
编辑:澄清一下,这是原始来源。这不是生成的输出;它旨在被组装并链接到一个库中。
我将 grph_256cls
更改为带有 PROC FAR
的过程,现在它可以正常工作了:
grph_cls256 PROC FAR
...
grph_cls256 ENDP
这个问题与 C 期望根据内存模型调用函数的方式有关。在大内存模型中,所有的函数调用都是far
。在尝试 call
时,我没有在 grph_256cls
子例程上标记这个假设,所以没有 push/pop 正确值的代码 onto/off 堆栈被组装起来。
我对汇编语言有些陌生,想了解它在旧系统上的工作原理。我了解到大内存模型使用远指针而小内存模型使用近指针,并且大模型中的 return 地址是 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
它仍然会立即挂起。在两种模式下编写汇编代码时是否有完整的差异列表,以便我更容易理解发生了什么?
编辑:澄清一下,这是原始来源。这不是生成的输出;它旨在被组装并链接到一个库中。
我将 grph_256cls
更改为带有 PROC FAR
的过程,现在它可以正常工作了:
grph_cls256 PROC FAR
...
grph_cls256 ENDP
这个问题与 C 期望根据内存模型调用函数的方式有关。在大内存模型中,所有的函数调用都是far
。在尝试 call
时,我没有在 grph_256cls
子例程上标记这个假设,所以没有 push/pop 正确值的代码 onto/off 堆栈被组装起来。