#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.