Если вы намереваетесь повторно открыть сегмент, например _DATA
, тогда сегмент должен соответствовать ранее объявленным атрибутам сегмента. Когда вы используете упрощенные сегменты DOS и директиву model
, по умолчанию используется выравнивание WORD для сегментов _TEXT
и _DATA
. Вы изменили выравнивание с WORD по умолчанию на BYTE и, таким образом, получаете отображаемую ошибку. В руководстве TASM 5 указано:
Неверно переопределены атрибуты сегмента
Директива SEGMENT повторно открывает сегмент, который был ранее определен, и пытается придать ему разные атрибуты. Например:
DATA SEGMENT BYTE PUBLIC
DATA ENDS
DATA SEGMENT PARA ; error, previously had byte alignment
DATA ENDS
Если вы повторно открываете сегмент, предоставленные вами атрибуты должны либо точно совпадать, либо полностью опускаться. Если вы не предоставляете никаких атрибутов при повторном открытии сегмента, будут использованы старые атрибуты.
У вас есть несколько вариантов. Один из них более простой, и он заключается в объединении кода и данных в сегменте кода:
ideal
model tiny
codeseg
startupcode
lea dx,[lpText]
mov ah,9
int 21h
exitcode
lpText: db "Hello, world!$"
end
Если вы собираете его, он должен сгенерировать программу с размером 25 байт :
00000100 BA0B01 mov dx,0x10b
00000103 B409 mov ah,0x9
00000105 CD21 int 0x21
00000107 B44C mov ah,0x4c
00000109 CD21 int 0x21
0000010B 48 dec ax
0000010C 656C gs insb
0000010E 6C insb
0000010F 6F outsw
00000110 2C20 sub al,0x20
00000112 776F ja 0x183
00000114 726C jc 0x182
00000116 642124 and [fs:si],sp
Альтернативой является не использовать директиву model
и объявлять свои собственные сегменты с нуля:
ideal
group DGROUP _DATA, _TEXT
segment _TEXT byte 'CODE'
org 100h
ends
segment _DATA byte 'DATA'
ends
segment _DATA
lpText db "Hello, world!$"
ends
segment _TEXT
_start:
lea dx,[lpText] ; or mov dx, offset lptext
mov ah,9
int 21h
ret ; COM programs that use TINY model
; can exit with a RET. DOS places 0000h
; on the stack when program starts. Returning
; to 0000h executes an INT 20h instruction at
; offset 0000h in the PSP
ends
end _start
Директивы startupcode
и exitcode
не работают вне упрощенной модели сегментов, поэтому вам нужно сгенерировать код самостоятельно. Поскольку я предполагаю, что вы используете модель tiny
для генерации программ DOS COM, вы можете использовать ret
для возврата из DOS, предполагая, что вам не нужно возвращать уровень ошибки. Это уменьшает размер программы. Нет необходимости устанавливать сегментные регистры, поскольку все CS = DS = ES = SS указывают на Префикс сегмента программы (PSP) , когда DOS запускает программу COM. Сгенерированная программа будет выглядеть так:
00000100 BA0801 mov dx,0x108
00000103 B409 mov ah,0x9
00000105 CD21 int 0x21
00000107 C3 ret
00000108 48 dec ax
00000109 656C gs insb
0000010B 6C insb
0000010C 6F outsw
0000010D 2C20 sub al,0x20
0000010F 776F ja 0x180
00000111 726C jc 0x17f
00000113 642124 and [fs:si],sp
Результирующая программа COM должна иметь размер 22 байта .
Если бы вы заменили ret
в предыдущем коде на:
mov ah,4ch
int 21h
Получившийся файл был бы размером 25 байтов и, что более важно, сегмент _DATA
не выровнен по границе СЛОВА:
00000100 BA0B01 mov dx,0x10b
00000103 B409 mov ah,0x9
00000105 CD21 int 0x21
00000107 B44C mov ah,0x4c
00000109 CD21 int 0x21
0000010B 48 dec ax
0000010C 656C gs insb
0000010E 6C insb
0000010F 6F outsw
00000110 2C20 sub al,0x20
00000112 776F ja 0x183
00000114 726C jc 0x182
00000116 642124 and [fs:si],sp