Сбой DOSBOX после /3 ключа, используемого для связывания исполняемого файла

#assembly #dos #tasm #i386

# #сборка #dos #тасм #i386

Вопрос:

У меня есть программа, написанная на tasm under dosbox (ее текст приведен ниже).
Is создается моим собственным компилятором, написанным на c, для абстрактного pl.
Я пытаюсь скомпилировать и запустить его следующим образом:

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

но я получаю и ошибку:

 relative jump out of range by 000fh bytes
 

Я знаю, что причиной этого являются инструкции

 ;
forStart0:
;
jmp forStart0
;
 

потому что эти метки слишком «далеко»

поэтому я помещаю .386 его в начало своей программы и снова компилирую. Теперь он проходит tasm command и завершается tlink с ошибкой

 32-bit record encountered in module use /3 option
 

так что командование сейчас такое:

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

Теперь он также tlink передает запятую и запускается сгенерированным .exe , а его вывод состоит из одной буквы T и dosbox завершается сбоем.
Если я также добавлю /m3 :

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

При этом dosbox выводится несколько строк бессмысленных символов после .exe запуска и останавливается выполнение.

Итак, мой вопрос таков: что не так и как это исправить? программа:

 ;.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,'<< 

РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не  /3  ключ, а  .386  директива
Если я скомпилирую свою любую программу с помощью  /3  - она будет работать так же, как и раньше. Но если я размещаю  .386  его, он выходит из строя перед циклами  input и всем остальным.


Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

erStr1 db 13,10,'strData not input_variable',13,10,'РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 - она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

erStr2 db 13,10,'Incorrectly data ',13,10,'РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 - она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

erStr3 db 13,10,'strData is too long ',13,10,'РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 - она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

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

;=======strData for output===================
MSign db ' ','РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 - она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

X_Str db 12 dup (0)
ten dw 10
X1 dw 0h
MX1 db 13,10,'>>РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы - это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 - она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.

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

.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
РЕДАКТИРОВАТЬ:
пришел к выводу, что я неправильно назвал причину проблемы — это был не /3 ключ, а .386 директива
Если я скомпилирую свою любую программу с помощью /3 — она будет работать так же, как и раньше. Но если я размещаю .386 его, он выходит из строя перед циклами input и всем остальным.

Комментарии:

1. Это вряд ли связано с /3 . У вашей программы просто проблема. Поскольку у вас, похоже, есть turbotools, используйте turbo debugger.

2. @Jester Я полагаю, вы ошибаетесь. Если я вручную удалю все jmp и jz из своей программы, она будет работать правильно. Он вводит и выводит числа. Очевидно, что без цикла while.

3. Например, если вы разбалансируете стек FPU, это может привести к сбою только в том случае, если вы выполняете цикл. Опять же, первое, что вы делаете, это считываете входные данные, вы имеете в виду, что это тоже не работает?

4. @DavidWohlferd как я уже упоминал, эта программа создается моим собственным компилятором. Для этого примера я использую только 2-уровневую вложенность. Но я, вероятно, могу сделать его 10-уровневым, чтобы расстояние быстро увеличивалось.

5. Моя версия tasm выдает warning: Assuming segment is 32 bit . Это, безусловно, звучит подозрительно.

Ответ №1:

Моя версия tasm излучает

* Предупреждение * Предполагается, что сегмент является 32-разрядным

Вы должны использовать .386 после .MODEL SMALL , чтобы сохранить 16-битные сегменты, или явно выделять 16-битные сегменты вместо использования упрощенных директив.

Комментарии:

1. Спасибо, это работает, но я могу опубликовать изображение, и вы увидите, что в моем dosbox нет предупреждений. У меня версия 0.74-3.

2. Я верю тебе. Вероятно, это другая версия. У меня 2.0.