【问题标题】:How do I translate DOS assembly targeted for the small memory model to the large memory model?如何将针对小内存模型的 DOS 程序集转换为大内存模型?
【发布时间】: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,它仍然会在之后挂起。在两种模式下编码汇编时是否有完整的差异列表,以便我更容易理解发生了什么?

编辑:澄清一下,这是原始来源。这不是生成的输出;它旨在组装并链接到库中。

【问题讨论】:

  • 请注意,在大代码模型中,函数调用将一个四字节的返回地址压入堆栈。您可能希望在 COLORGPAGE 的定义中考虑这一点。
  • 参数原来是[bp+4][bp+6],两个字节的返回地址压栈,所以我给每个增加了两个字节。
  • 您需要展示完整的代码以及构建和运行它所采取的所有步骤,以便我们重现问题。如有必要,将调用此函数的 C 代码减少到重现问题所需的最低限度。使您帖子中的代码与您使用的代码完全相同。
  • 只是猜测:在大型模型中,TASM 可能需要明确的retf
  • 我将它们全部替换为retfs,但并没有什么不同。但是我确实发现,如果我完全跳过grph_cls256,就不会发生崩溃。

标签: memory assembly dos


【解决方案1】:

我将grph_256cls 更改为带有PROC FAR 的过程,现在它可以正常工作了:

grph_cls256 PROC FAR
  ...
grph_cls256 ENDP

这个问题与 C 期望函数如何根据内存模型被调用有关。在大内存模型中,所有函数调用都是far。当我尝试call 时,我没有在grph_256cls 子例程上标记这个假设,因此组装了没有将正确值推入/弹出堆栈的代码。

【讨论】:

  • 这与 C 的期望无关,因为调用 grph_256cls 的不是 C 代码。
  • @RossRidge:啊,但确实如此。 TASM 会根据 C 的预期自动调整。
  • @Joshua 不,不是。这就是问题所在,如果是这样的话,它会一直这样做。
  • @RossRidge:PROC 与 PROC FAR 是您更改内存模型的方式。在他改变这一点之前,他的改变一直在两种非工作状态之间摇摆不定,这两种状态源自混合记忆模型。
  • @Joshua 不,这不是他所做的改变。
猜你喜欢
  • 2014-07-08
  • 2012-08-11
  • 2014-05-01
  • 2015-02-06
  • 2018-10-27
  • 1970-01-01
  • 2020-03-09
  • 2020-06-24
  • 2011-03-03
相关资源
最近更新 更多