установить выравнивание сегмента данных в идеальном режиме TASM - PullRequest
3 голосов
/ 06 августа 2020

Исходный код моей сборки:

ideal 
model tiny 
segment _data byte  ; TASM doesn't accept it. 
ends _data 
 
dataseg 
align 1  ; Doesn't decrease the segment alignment. 
lpText  db "Hello, world!$" 
 
codeseg 
        startupcode 
        lea dx,[lpText] 
        mov ah,9 
        int 21h 
        exitcode 
end 

TASM 5.0 выдает ошибку Неверно переопределены атрибуты сегмента для строки с byte.

Как можно ли изменить сегмент данных на выравнивание по байтам в идеальном режиме?

Мне это нужно, потому что я не хочу лишний 0 байт в сгенерированном файле .com перед lpText . Я хочу, чтобы файл .com был как можно меньше.

1 Ответ

5 голосов
/ 07 августа 2020

Если вы намереваетесь повторно открыть сегмент, например _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
...