使用 8086 MS-DOS 程序集显示字符串数组
Display an Array of Strings using 8086 MS-DOS Assembly
我正在尝试使用 Borland Turbo Assembler 5(据我所知类似于 MASM 语法)为 MS-DOS 显示一个数组,第一个字符串打印但其余字符串不打印。
关于使用 8086 兼容 MS-DOS 程序集实现此目的的最佳方法有何建议?
; TEST.COM:
stdin equ 0 ; standard input handle
stdout equ 1 ; standard output handle
stderr equ 2 ; standard error handle
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII linefeed
escape equ 1Bh ; escape
fg_black equ escape,'[30m'
fg_red equ escape,'[31m'
_TEXT segment word public 'CODE'
org 100h
assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
main proc near
mov bx,dir_array
mov ah,9
dirloop:
lea dx,[bx]
int 21h
add bx,2
cmp bx,offset dir_array+dir_array_size
jl dirloop
mov ax,4C00h
int 21h
main endp
msg1 db cr,lf
db 'DOS FindFirst API Test',cr,lf
dir_array dw dos_dir,int21_3E_dir,test_dir1,test_dir2,test_dir3
end1 db '$'
dir_array_size equ $-dir_array
end2 db '$'
dos_dir db 'C:\DOS',cr,lf,'$'
int21_3E_dir db "C:\DOS\INT21_3E",cr,lf,'$'
test_dir1 db "C:\DOS\INT21_3E\TEST1",cr,lf,'$'
test_dir2 db "C:\DOS\INT21_3E\TEST2",cr,lf,'$'
test_dir3 db "C:\DOS\INT21_3E\TEST3",cr,lf,'$'
test_file1 db "C:\DOS\INT21_3E\ARC.TXT",0
test_file2 db "C:\DOS\INT21_3E\RONLY.TXT",0
test_file3 db "C:\DOS\INT21_3E\SYSTEM.TXT",0
test_file4 db "C:\DOS\INT21_3E\HIDDEN.TXT",0
msg1_len equ $-msg1
_TEXT ends
end main
使用 turbo 调试器检查我可以看到“bx”被分配了值 dos_dir 但我希望它会指定 dir_array 的地址.
第一个字符串在 13E:
输出:
固定代码,使用lea指令加载数组,'end1'标记数组结束。
stdin equ 0 ; standard input handle
stdout equ 1 ; standard output handle
stderr equ 2 ; standard error handle
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII linefeed
escape equ 1Bh ; escape
fg_black equ escape,'[30m'
fg_red equ escape,'[31m'
_TEXT segment word public 'CODE'
org 100h
assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
main proc near
lea bx,dir_array
mov ah,9
dirloop:
mov dx,[bx]
int 21h
add bx,2
cmp bx,offset end1
jl dirloop
mov ax,4C00h
int 21h
main endp
msg1 db cr,lf
db 'DOS FindFirst API Test',cr,lf
dir_array dw dos_dir,int21_3E_dir,test_dir1,test_dir2,test_dir3
end1 db '$'
dir_array_size equ $-dir_array
end2 db '$'
dos_dir db 'C:\DOS',cr,lf,'$'
int21_3E_dir db "C:\DOS\INT21_3E",cr,lf,'$'
test_dir1 db "C:\DOS\INT21_3E\TEST1",cr,lf,'$'
test_dir2 db "C:\DOS\INT21_3E\TEST2",cr,lf,'$'
test_dir3 db "C:\DOS\INT21_3E\TEST3",cr,lf,'$'
test_file1 db "C:\DOS\INT21_3E\ARC.TXT",0
test_file2 db "C:\DOS\INT21_3E\RONLY.TXT",0
test_file3 db "C:\DOS\INT21_3E\SYSTEM.TXT",0
test_file4 db "C:\DOS\INT21_3E\HIDDEN.TXT",0
msg1_len equ $-msg1
_TEXT ends
end main
I can see bx
is being assigned the value dos_dir but I was hoping it would specify the address of dir_array.
TASM 遵循 MASM 风格,其中写入 mov bx, dir_array
将从内存中获取一个单词并将其存储在 BX
中,但 mov bx, offset dir_array
会将有效地址存储在 BX
中.也可以通过lea bx, dir_array
获取有效地址,但会浪费一个字节。 mov - offset
使用 3 个字节 vs lea
使用 4 个字节。
因为 dir_array 包含 5 个单词并且您向其附加了一个字节,所以 dir_array_size equ $-dir_array
等式将设置 dir_array_size等于11。这意味着循环将运行太长!只需删除额外的字节并将条件视为无符号,毕竟它是一个计数。
一个解决方案
mov si, offset dir_array
dirloop:
lodsw
mov dx, ax
mov ah, 09h ; DOS.PrintString
int 21h
cmp si, offset dir_array + dir_array_size
jb dirloop
...
dir_array dw dos_dir, int21_3E_dir, test_dir1, test_dir2, test_dir3
dir_array_size equ $-dir_array
另一种解决方案
xor bx, bx
dirloop:
mov dx, dir_array[bx]
mov ah, 09h ; DOS.PrintString
int 21h
add bx, 2
cmp bx, dir_array_size
jb dirloop
...
dir_array dw dos_dir, int21_3E_dir, test_dir1, test_dir2, test_dir3
dir_array_size equ $-dir_array
我正在尝试使用 Borland Turbo Assembler 5(据我所知类似于 MASM 语法)为 MS-DOS 显示一个数组,第一个字符串打印但其余字符串不打印。 关于使用 8086 兼容 MS-DOS 程序集实现此目的的最佳方法有何建议?
; TEST.COM:
stdin equ 0 ; standard input handle
stdout equ 1 ; standard output handle
stderr equ 2 ; standard error handle
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII linefeed
escape equ 1Bh ; escape
fg_black equ escape,'[30m'
fg_red equ escape,'[31m'
_TEXT segment word public 'CODE'
org 100h
assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
main proc near
mov bx,dir_array
mov ah,9
dirloop:
lea dx,[bx]
int 21h
add bx,2
cmp bx,offset dir_array+dir_array_size
jl dirloop
mov ax,4C00h
int 21h
main endp
msg1 db cr,lf
db 'DOS FindFirst API Test',cr,lf
dir_array dw dos_dir,int21_3E_dir,test_dir1,test_dir2,test_dir3
end1 db '$'
dir_array_size equ $-dir_array
end2 db '$'
dos_dir db 'C:\DOS',cr,lf,'$'
int21_3E_dir db "C:\DOS\INT21_3E",cr,lf,'$'
test_dir1 db "C:\DOS\INT21_3E\TEST1",cr,lf,'$'
test_dir2 db "C:\DOS\INT21_3E\TEST2",cr,lf,'$'
test_dir3 db "C:\DOS\INT21_3E\TEST3",cr,lf,'$'
test_file1 db "C:\DOS\INT21_3E\ARC.TXT",0
test_file2 db "C:\DOS\INT21_3E\RONLY.TXT",0
test_file3 db "C:\DOS\INT21_3E\SYSTEM.TXT",0
test_file4 db "C:\DOS\INT21_3E\HIDDEN.TXT",0
msg1_len equ $-msg1
_TEXT ends
end main
使用 turbo 调试器检查我可以看到“bx”被分配了值 dos_dir 但我希望它会指定 dir_array 的地址.
第一个字符串在 13E:
输出:
固定代码,使用lea指令加载数组,'end1'标记数组结束。
stdin equ 0 ; standard input handle
stdout equ 1 ; standard output handle
stderr equ 2 ; standard error handle
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII linefeed
escape equ 1Bh ; escape
fg_black equ escape,'[30m'
fg_red equ escape,'[31m'
_TEXT segment word public 'CODE'
org 100h
assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
main proc near
lea bx,dir_array
mov ah,9
dirloop:
mov dx,[bx]
int 21h
add bx,2
cmp bx,offset end1
jl dirloop
mov ax,4C00h
int 21h
main endp
msg1 db cr,lf
db 'DOS FindFirst API Test',cr,lf
dir_array dw dos_dir,int21_3E_dir,test_dir1,test_dir2,test_dir3
end1 db '$'
dir_array_size equ $-dir_array
end2 db '$'
dos_dir db 'C:\DOS',cr,lf,'$'
int21_3E_dir db "C:\DOS\INT21_3E",cr,lf,'$'
test_dir1 db "C:\DOS\INT21_3E\TEST1",cr,lf,'$'
test_dir2 db "C:\DOS\INT21_3E\TEST2",cr,lf,'$'
test_dir3 db "C:\DOS\INT21_3E\TEST3",cr,lf,'$'
test_file1 db "C:\DOS\INT21_3E\ARC.TXT",0
test_file2 db "C:\DOS\INT21_3E\RONLY.TXT",0
test_file3 db "C:\DOS\INT21_3E\SYSTEM.TXT",0
test_file4 db "C:\DOS\INT21_3E\HIDDEN.TXT",0
msg1_len equ $-msg1
_TEXT ends
end main
I can see
bx
is being assigned the value dos_dir but I was hoping it would specify the address of dir_array.
TASM 遵循 MASM 风格,其中写入 mov bx, dir_array
将从内存中获取一个单词并将其存储在 BX
中,但 mov bx, offset dir_array
会将有效地址存储在 BX
中.也可以通过lea bx, dir_array
获取有效地址,但会浪费一个字节。 mov - offset
使用 3 个字节 vs lea
使用 4 个字节。
因为 dir_array 包含 5 个单词并且您向其附加了一个字节,所以 dir_array_size equ $-dir_array
等式将设置 dir_array_size等于11。这意味着循环将运行太长!只需删除额外的字节并将条件视为无符号,毕竟它是一个计数。
一个解决方案
mov si, offset dir_array
dirloop:
lodsw
mov dx, ax
mov ah, 09h ; DOS.PrintString
int 21h
cmp si, offset dir_array + dir_array_size
jb dirloop
...
dir_array dw dos_dir, int21_3E_dir, test_dir1, test_dir2, test_dir3
dir_array_size equ $-dir_array
另一种解决方案
xor bx, bx
dirloop:
mov dx, dir_array[bx]
mov ah, 09h ; DOS.PrintString
int 21h
add bx, 2
cmp bx, dir_array_size
jb dirloop
...
dir_array dw dos_dir, int21_3E_dir, test_dir1, test_dir2, test_dir3
dir_array_size equ $-dir_array