首页 > 解决方案 > 使用 8086 MS-DOS 程序集显示字符串数组

问题描述

我正在尝试为 MS-DOS 使用 Borland Turbo Assembler 5(据我所知类似于 MASM 语法)显示一个数组,第一个字符串打印但其余的不打印。关于使用 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:

在此处输入图像描述

输出:

在此处输入图像描述

标签: assemblydosx86-16

解决方案


我可以看到bx被分配了值dos_dir但我希望它会指定dir_array的地址。

TASM 遵循 MASM 样式,其中写入mov bx, dir_array将从内存中获取一个单词并将其存储在 中BX,但mov bx, offset dir_array会将有效地址存储在 中BX。您也可以通过 获取有效地址lea bx, dir_array,但这会浪费一个字节。mov - offset使用 3 个字节与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

推荐阅读