如何在汇编程序中创建字符串数组并使用它们?
我试试:
arrayOfWords BYTE "BICYCLE", "CANOE", "SCATEBOARD", "OFFSIDE", "TENNIS"
之后我想打印第二个单词,但它不起作用
mov edx, offset arrayOfWords[2]
call WriteString
但是他给我打印了全世界。
答案 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结尾的字符串作为字符串。将这一组字符视为字符串数组有两种方法。
在内存中搜索正确的地址到所需的字符串。在每个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
构建指向字符串的指针数组:
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
BTW:与其他语言一样,索引从0开始。第二个字符串是index = 1,第三个索引= 2.