【问题标题】:Display an Array of Strings using 8086 MS-DOS Assembly使用 8086 MS-DOS 程序集显示字符串数组
【发布时间】:2021-11-04 06:17:56
【问题描述】:

我正在尝试为 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:

输出:

【问题讨论】:

  • 在我看来,当您第一次阅读 [bx] 时,您正在从数组末尾之外读取数据,并且在读取数组中的第一个元素之前退出循环。
  • 更新了更多信息和调试器的输出

标签: assembly dos x86-16


【解决方案1】:

我可以看到 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

【讨论】:

    【解决方案2】:

    修正代码,使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 2014-01-16
      • 2020-12-23
      相关资源
      最近更新 更多