If you intend to reopen a segment like _DATA
then the segment must match the previously declared segment attributes. When you use the simplified DOS segments and the model
directive the default is WORD alignment for the _TEXT
and _DATA
segments. You have changed the alignment from the default of WORD to BYTE and thus are getting the error you see. The TASM 5 manual states:
Segment attributes illegally redefined
A SEGMENT directive reopen a segment that has been previously defined,
and tries to give it different attributes. For example:
DATA SEGMENT BYTE PUBLIC
DATA ENDS
DATA SEGMENT PARA ; error, previously had byte alignment
DATA ENDS
If you reopen a segment, the attributes you supply must either match
exactly or be omitted entirely. If you don't supply any attributes
when reopening a segment, the old attributes will be used.
You have a couple of choices. One is the simpler one and that is to combine the code and data in the code segment:
ideal
model tiny
codeseg
startupcode
lea dx,[lpText]
mov ah,9
int 21h
exitcode
lpText: db "Hello, world!$"
end
If you were to assemble this it should generate a program with a size of 25 bytes:
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
An alternative is to not use the model
directive and declare your own segments from scratch:
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
The startupcode
and exitcode
directives don't work outside the simplified segment model so you need to generate the code yourself. Since I am assuming you are using tiny
model to generate DOS COM programs you can use ret
to return from DOS assuming you don't need to return an error level. This reduces the size of the program. There is no need to set the segment registers as CS=DS=ES=SS are all pointing at the Program Segment Prefix (PSP) when DOS starts running the COM program. The program generated would look like this:
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
The resulting COM program should be a size of 22 bytes.
If you had replaced ret
in the previous code with:
mov ah,4ch
int 21h
The resulting file would be a size of 25 bytes and more importantly the _DATA
segment is not aligned on a WORD boundary:
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