在 TASM 理想模式下设置数据段的对齐方式

pts*_*pts 3 x86 assembly dos tasm x86-16

我的汇编源代码:

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 
Run Code Online (Sandbox Code Playgroud)

TASM 5.0 给了我错误段属性非法重新定义其中的行byte

如何在理想模式下将数据段更改为字节对齐?

我需要它,因为我不希望在lpText前面生成的 .com 文件中有一个额外的 0 字节。我希望 .com 文件尽可能小。

Mic*_*tch 5

如果您打算重新打开一个段,_DATA那么该段必须与之前声明的段属性匹配。当您使用简化的 DOS 段和model指令时,默认值是_TEXT_DATA段的WORD 对齐。您已将对齐方式从默认的 WORD 更改为 BYTE,因此出现了您看到的错误。所述TASM 5手册中指出:

段属性非法重新定义

SEGMENT 指令重新打开先前定义的段,并尝试为其赋予不同的属性。例如:

DATA SEGMENT BYTE PUBLIC
DATA ENDS
DATA SEGMENT PARA                 ; error, previously had byte alignment
DATA ENDS
Run Code Online (Sandbox Code Playgroud)

如果您重新打开一个段,您提供的属性必须完全匹配或完全省略。如果在重新打开段时不提供任何属性,则将使用旧属性。


你有几个选择。一种是比较简单的,就是将代码段中的代码和数据结合起来:

ideal
model tiny

codeseg
        startupcode
        lea dx,[lpText]
        mov ah,9
        int 21h
        exitcode
lpText:  db "Hello, world!$"

end
Run Code Online (Sandbox Code Playgroud)

如果您要组装它,它应该生成一个大小为 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
Run Code Online (Sandbox Code Playgroud)

另一种方法是不使用该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
Run Code Online (Sandbox Code Playgroud)

startupcodeexitcode,所以你需要自己生成的代码指令不简化段模型之外工作。由于我假设您正在使用tiny模型来生成 DOS COM 程序,因此ret假设您不需要返回错误级别,您可以使用它从 DOS 返回。这减少了程序的大小。不需要设置段寄存器,因为当 DOS 开始运行 COM 程序时,CS=DS=ES=SS 都指向程序段前缀 (PSP)。生成的程序如下所示:

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
Run Code Online (Sandbox Code Playgroud)

生成的 COM 程序的大小为 22 字节


如果您ret在之前的代码中替换为:

mov ah,4ch
int 21h
Run Code Online (Sandbox Code Playgroud)

生成的文件大小为 25 字节,更重要的_DATA是该段未在 WORD 边界上对齐:

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
Run Code Online (Sandbox Code Playgroud)