Sinuous514
Sinuous514

Reputation: 143

How do I translate DOS assembly targeted for the small memory model to the large memory model?

I'm somewhat new to assembly language and wanted to understand how it works on an older system. I understand that the large memory model uses far pointers while the small memory model uses near pointers, and that the return address in the large model is 4 bytes instead of two, so the first parameter changes from [bp+4] to [bp+6]. However, in the process of adapting a graphics library from a small to a large model, there are other subtle things that I don't seem to understand. Running this code with a large memory model from C is supposed to clear the screen, but instead it hangs the system (it was assembled with 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

It hangs at the ret at the end of grph_256cls. In fact, even if I immediately ret from the beginning of the function it still hangs right after. Is there a comprehensive list of differences when coding assembly in the two modes, so I can more easily understand what's happening?

EDIT: To clarify, this is the original source. This is not generated output; it's intended to be assembled and linked into a library.

Upvotes: 1

Views: 152

Answers (1)

Sinuous514
Sinuous514

Reputation: 143

I changed grph_256cls to a procedure with PROC FAR and it now works without issue:

grph_cls256 PROC FAR
  ...
grph_cls256 ENDP

The issue had to do with how C expects functions to be called depending on the memory model. In the large memory model, all function calls are far. I hadn't labeled this assumption on the grph_256cls subroutine when trying to call it, so code that didn't push/pop the right values onto/off the stack was assembled instead.

Upvotes: 1

Related Questions