Search code examples
assemblydostasmi386

DOSBOX crashes after /3 key used for linking executable


I have a program written in tasm under dosbox (its text is provided below).
Is is produced by my own c-written compiler for abstract pl.
I am trying to compile and run it in the following way:

mount c *some path*
c:
tasm PROGRA~1.asm
tlink PROGRA~1.obj 
PROGRA~1.exe

but i am getting and error:

relative jump out of range by 000fh bytes

I know the reason for this is the instructions

;
forStart0:
;
jmp forStart0
;

because these labels are too "far away"

so i put .386 at the top of my program and compile it again. Now it passes tasm command and fails on tlink with error

32-bit record encountered in module use /3 option

so command now is:

mount c *path *
c:
tasm PROGRA~1.asm
tlink /3 PROGRA~1.obj 
PROGRA~1.exe

Now it passes also tlink commad and runs produced .exe and its output is single letter T and dosbox crashes. If i also add /m3:

mount c *path *
c:
tasm /m3 PROGRA~1.asm
tlink /3 PROGRA~1.obj 
PROGRA~1.exe

With this dosbox output few rows of meaningless symbols after .exe run and stops execution.

So my question is: what is wrong and how to fix it? program:

;.386
DOSSEG
.MODEL SMALL
.STACK 100h
.DATA
MY_MUL MACRO X,Y,Z
    mov z,0
    mov z+2,0
    mov ax,x
    mul y
    mov z,ax
    mov z+2,dx
    mov ax,x+2
    mul y
    add z+2,ax
    mov ax,z
    mov dx,z+2
ENDM

    _idea   dd  00h
    _ideb   dd  00h
    _idec   dd  00h
    lb1 dw  0h
    lb2 dw  0h
    buf_if  dw  0h
buf dd  0
rc  dw  0
;======strData for input() functions======
    erFlag  db  0
    TStr    db  10 dup (0)
    TBin    dw  0,0
    MaxLen  dw  0
    FlagS   db  0
    Mul10   dw  1,0
    my_z    dw  0,0

    In_Str  db  13,10,'<< $'
    erStr1  db  13,10,'strData not input_variable',13,10,'$'
    erStr2  db  13,10,'Incorrectly data ',13,10,'$'
    erStr3  db  13,10,'strData is too long ',13,10,'$'
;======================================

;=======strData for output===================
    MSign   db  '+','$'
    X_Str   db  12 dup (0)
    ten dw  10
    X1  dw  0h
    MX1 db  13,10,'>> $'
;======================================

.CODE
start:
    mov ax,@data
    mov ds,ax
finit
fstcw rc
or rc,0c00h
fldcw rc
    call input
    fild buf
    fistp _idea
    call input
    fild buf
    fistp _ideb
    call input
    fild buf
    fistp _idec
forStart0:
    fild _idea
    mov word ptr buf,00002h
    fild buf
    fsub
    fistp buf
    fldz 
    fild buf
    call eq_
    call ltNot
    fistp buf
    mov ax,word ptr buf
    cmp ax,0
    jz forFinish0
    mov word ptr buf,000deh
    fild buf
    fistp buf
    call output
    fild _idea
    mov word ptr buf,00001h
    fild buf
    fsub
    fistp _idea
forStart1:
    fild _ideb
    mov word ptr buf,00004h
    fild buf
    fsub
    fistp buf
    fldz 
    fild buf
    call eq_
    call ltNot
    fistp buf
    mov ax,word ptr buf
    cmp ax,0
    jz forFinish1
    mov word ptr buf,0007bh
    fild buf
    fistp buf
    call output
    fild _ideb
    mov word ptr buf,00001h
    fild buf
    fsub
    fistp _ideb
jmp forStart1
forFinish1:
jmp forStart0
forFinish0:
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00001h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00000h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00001h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00000h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00001h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00001h
    fild buf
    mov word ptr buf,00000h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00000h
    fild buf
    mov word ptr buf,00001h
    fild buf
    call ltAnd
    call ltAnd
    fistp _idea
    fild _idea
    fistp buf
    call output
;======================================
MOV AH,4Ch
INT 21h

;====Input procedure Input()=============
INPUT PROC

    push ax
    push bx
    push cx
    push dx
    push di
    push si

    lea dx,In_Str
    mov ah,09
    int 21h
    mov di,offset buf
    mov MaxLen,5
    mov cx,MaxLen

    mov si,0

  In_00:
    mov ah,01
    int 21h
    cmp al,0Dh
    je In_1
    cmp al,'-'
    jne In_0
    mov FlagS,1
    jmp In_00

  In_0:
    mov dl,al
    call CHECK_BYTE
    mov TStr[si],dl
    inc si
    loop In_00

  In_1:
    push si
    dec si
    cmp cx,MaxLen
    jne In_2
    lea dx,erStr1
    mov ah,09
    int 21h
    mov erFlag,1
    jmp In_5

  In_2:
    mov bh,0
    mov bl,TStr[si]
    MY_MUL Mul10,bx,my_z
    add TBin,ax
    adc TBin+2,dx
    mov bh,0
    mov bl,10
    MY_MUL Mul10,bx,my_z
    mov Mul10,ax
    mov Mul10+2,dx
    dec si
    cmp si,0
    jge In_2
    mov ax,TBin
    mov dx,TBin+2
    pop si
    cmp si,MaxLen
    jl In_3
    cmp MaxLen,5
    jl In_2_1
    js In_Err
    cmp dx,7FFFh
    ja In_Err
    jmp In_3

  In_2_1:
    cmp MaxLen,5
    jl In_2_2
    cmp dx,00
    ja In_Err
    cmp ah,7fh
    ja In_Err
    jmp In_3

  In_2_2:
    cmp ax,007Fh
    jbe In_3

  In_Err:
    lea dx,erStr3
    mov ah,09
    int 21h
    mov erFlag,1
    jmp In_5

  In_3:
    cmp FlagS,1
    jne In_4
    mov bx,0
    sub bx,ax
    mov ax,bx
    mov bx,0
    sbb bx,dx
    mov dx,bx

  In_4:
    mov [di],ax
    mov [di+2],dx
    mov TBin,0
    mov TBin+2,0
    mov Mul10,1
    mov Mul10+2,0
    mov FlagS,0

  In_5:

    pop si
    pop di
    pop dx
    pop cx
    pop bx
    pop ax

    ret
input ENDP

CHECK_BYTE  PROC
    sub dl,30h
    cmp dl,00
    jl ErS
    cmp dl,0Ah
    jl GO

  ErS:
    lea dx,erStr2
    mov ah,09
    int 21h

  GO:
    ret
CHECK_BYTE ENDP
;======================================


;===Output procedure output()=============

output PROC

    push ax
    push bx
    push cx
    push dx
    push di
    push si

    mov cl,byte ptr buf+3
    and cl,80h
    je m6
    fild buf
    fchs
    fistp buf
    mov MSign,'-'

  M6:
    mov cx,5
    mov di,0

  O_1:
    ffree st(0)
    ffree st(1)
    fild ten
    fild buf
    fprem
    fistp X1
    mov dl,byte ptr X1
    add dl,30h
    mov X_Str[di],dl
    inc di
    fild buf
    fxch st(1)
    fdiv
    frndint
    fistp buf
    loop O_1

    mov dx,offset MX1
    mov ah,09
    int 21h
    mov dl,MSign
    mov ah,02
    int 21h
    inc di
    mov cx,7

  O_2:
    mov dl,X_Str[di]
    mov ah,02h
    int 21h
    dec di
    loop O_2

    mov MSign,'+'

    pop si
    pop di
    pop dx
    pop cx
    pop bx
    pop ax

    ret
output ENDP
;======================================


;===Procedure mod_====================

mod_ PROC

    fistp lb1
    fistp lb2
    fild lb1
    fild lb2
    fprem
    ret
mod_ ENDP
;======================================


;===Procedure ltAnd====================

ltAnd PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax,lb1
    cmp ax,0
    jnz true_and1
    jz false_and

  true_and1:
    mov ax,lb2
    cmp ax,0
    jnz true_and

 false_and:
    fldz
    jmp l_and

  true_and:
    fld1

  l_and:

    popf
    pop dx
    pop ax

    ret
ltAnd ENDP
;======================================


;===Procedure ltOr======================

ltOr PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax,lb1
    cmp ax,0
    jnz true_or
    mov ax,lb2
    cmp ax,0
    jnz true_or
    fldz
    jmp l_or

  true_or:
    fld1

  l_or:

    popf
    pop dx
    pop ax

    ret
ltOr ENDP
;======================================


;===Procedure ltNot====================

ltNot PROC

    push ax
    pushf
    fistp lb1
    mov ax,lb1
    cmp ax,0
    jne is_true
    fld1
    jmp l_not

  is_true:
    fldz

  l_not:

    popf
    pop ax

    ret
ltNot ENDP
;======================================


;===Procedure eq_======================

eq_ PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax,lb1
    mov dx,lb2
    cmp ax,dx
    jne not_eq
    fld1
    jmp l_eq

  not_eq:
    fldz

  l_eq:
    popf
    pop dx
    pop ax

    ret
eq_ ENDP
;======================================


;===Procedure ltGreate======================

ltGreate PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax,lb1
    mov dx,lb2
    cmp dx,ax
    jl lov
    fld1
    jmp l_ge

  lov:
    fldz

  l_ge:
    popf
    pop dx
    pop ax

    ret
ltGreate ENDP
;======================================


;===Procedure ltLess======================

ltLess PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax, lb1
    mov dx, lb2
    cmp dx,ax
    jge gr

  lo:
    fld1
    jmp l_le

  gr:
    fldz

  l_le:
    popf
    pop dx
    pop ax

    ret
ltLess ENDP
;======================================


;===Procedure ltLessEq======================

ltLessEq PROC

    push ax
    push dx
    pushf
    fistp lb1
    fistp lb2
    mov ax, lb1
    mov dx, lb2
    cmp dx,ax
    jg greq

  loeq:
    fld1
    jmp l_leeq

  greq:
    fldz

  l_leeq:
    popf
    pop dx
    pop ax

    ret
ltLessEq ENDP
;======================================

;======================================

end start
END

EDIT: came to the conclusion that I incorrectly named the cause of the problem - it was not a /3 key, but a .386 directive If i compile my any program using /3 - it works as earlier. But if i place .386 it crashes before loops\input and anything else.


Solution

  • My version of tasm emits a

    *Warning* Assuming segment is 32 bit

    You should use the .386 after the .MODEL SMALL to keep segments 16 bit, or explicitly emit 16 bit segments instead of using the simplified directives.