从字符串数组中打印一个字符串

时间:2017-06-03 07:02:01

标签: arrays string assembly irvine32

如何在汇编程序中创建字符串数组并使用它们?

我试试:

arrayOfWords BYTE "BICYCLE", "CANOE", "SCATEBOARD", "OFFSIDE", "TENNIS"

之后我想打印第二个单词,但它不起作用

    mov edx, offset arrayOfWords[2]
    call WriteString

但是他给我打印了全世界。

2 个答案:

答案 0 :(得分:2)

arrayOfWords BYTE "BICYCLE", "CANOE", "SCATEBOARD", "OFFSIDE", "TENNIS"

是另一种写作方式

arrayOfWords BYTE "BICYCLECANOESCATEBOARDOFFSIDETENNIS"

这远不是一个阵列 此外,mov edx, offset arrayOfWords[2]不是数组索引 程序集中的括号用于表示addressing mode,而不是数组索引 这就是为什么我不能停止强调 NOT 1 使用语法<symbol>[<displacement>](你的arrayOfWords[2]) - 这是一个非常愚蠢和令人困惑的写[<symbol> + <displacement>]的方式(在你的情况下[arrayOfWords + 2])。

您可以看到mov edx, OFFSET [arrayOfWords + 2](在我看来更清晰地写为mov edx, OFFSET arrayOfWords + 2,因为指令没有访问任何内存)只是加载edx BICYCLE 中的C 字符(大字符串的第三个字符)。

MASM有许多高级机器,我从不费心学习,但在快速浏览脚注中链接的手册之后,它似乎没有对阵列的高级支持。
这是一件好事,我们可以使用更清洁的装配。

字符串数组不是连续的字符串块,它是指针到字符串的连续块。
字符串可以在任何地方。

arrayOfWords  DWORD  OFFSET strBicycle, 
                     OFFSET strCanoe,
                     OFFSET strSkateboard,
                     OFFSET strOffside,
                     OFFSET strTennis

strBicycle    BYTE "BICYCLE",0
strCanoe      BYTE "CANOE", 0
strSkateboard BYTE "SKATEBOARD", 0
strOffside    BYTE "OFFSIDE", 0
strTennis     BYTE "TENNIS", 0

请记住:数组的优点是持续访问时间;如果要将所有字符串放在一起,我们将得到一个更紧凑的数据结构,但没有恒定的访问时间,因为无法知道字符串的起始位置,而是扫描整个字符串。
对于指针,我们有持续的访问时间,一般来说,我们要求数组的所有元素都是同类的,就像指针一样。

要在数组中加载 i-th 2 字符串的地址,我们只需读取 i-th 指针。
假设 i ecx然后

mov edx, DWORD PTR [arrayOfWords + ecx*4]
call writeString

因为每个指针都是四个字节。

如果你想读取字符串 i 的字节 j ,那么假设 j ebx {ecx中:

mov esi, DWORD PTR [arrayOfWords + ecx*4]
mov al, BYTE PTR [esi + ebx]

使用的寄存器是任意的。

1 尽管微软在其MASM 6.1 manual中写道:

  

引用数组
  数组中的每个元素都以索引号引用,从零开始。数组索引显示在数组名称后面的括号中,如

     

array[9]

     

汇编语言索引与索引号的高级语言中的索引不同   始终对应于元素的位置。例如,在C中,array [9]引用数组   第十个元素,无论每个元素的大小是1个字节还是8个字节。   在汇编语言中,元素的索引是指元素与数组开头之间的字节数。

2 从零开始计数。

答案 1 :(得分:1)

arrayOfWords不是数组,甚至不是变量。它只是一个标签告诉汇编器它可以在哪里找到一些东西,在这种情况下是一堆字符。 Irvine的WriteString期望以null结尾的字符串作为字符串。将这一组字符视为字符串数组有两种方法。

  1. 在内存中搜索正确的地址到所需的字符串。在每个null处开始一个新字符串。

    INCLUDE Irvine32.inc
    
    .DATA
    manyWords BYTE "BICYCLE", 0
        BYTE "CANOE", 0
        BYTE "SCATEBOARD", 0
        BYTE "OFFSIDE", 0
        BYTE "TENNIS", 0
        BYTE 0                              ; End of list
    len equ $ - manyWords
    
    .CODE
    main PROC
    
        mov edx, 2                          ; Index
        call find_str                       ; Returns EDI = pointer to string
    
        mov edx, edi
        call WriteString                    ; Irvine32: Write astring pointed to by EDX
    
        exit                                ; Irvine32: ExitProcess
    main ENDP
    
    find_str PROC                           ; ARG: EDX = index
    
        lea edi, manyWords                  ; Address of string list
    
        mov ecx, len                        ; Maximal number of bytes to scan
        xor al, al                          ; Scan for 0
    
        @@:
        sub edx, 1
        jc done                             ; No index left to scan = string found
        repne scasb                         ; Scan for AL
        jmp @B                              ; Next string
    
        done:
        ret
    find_str ENDP                           ; RESULT: EDI pointer to string[edx]
    
    END main
    
  2. 构建指向字符串的指针数组:

    INCLUDE Irvine32.inc
    
    .DATA
    wrd0 BYTE "BICYCLE", 0
    wrd1 BYTE "CANOE", 0
    wrd2 BYTE "SCATEBOARD", 0
    wrd3 BYTE "OFFSIDE", 0
    wrd4 BYTE "TENNIS", 0
    
    pointers DWORD OFFSET wrd0, OFFSET wrd1, OFFSET wrd2, OFFSET wrd3, OFFSET wrd4
    
    .CODE
    main PROC
    
        mov ecx, 2                          ; Index
        lea edx, [pointers + ecx * 4]       ; Address of pointers[index]
        mov edx, [edx]                      ; Address of string
        call WriteString
    
        exit                                ; Irvine32: ExitProcess
    main ENDP
    
    END main
    
  3. BTW:与其他语言一样,索引从0开始。第二个字符串是index = 1,第三个索引= 2.