我对如何使用x86程序集在堆栈上创建字符串和空数组感到困惑。
要创建一个字符串,我有......
PUSH .ascii "myString"
我对如何创建一个空数组感到困惑。我理解创建一个元素为0的数组,看起来像......
PUSH 0
不确定如何创建一个空数组,我不确定这是否是在堆栈上创建字符串的正确方法。
答案 0 :(得分:3)
你可以把它分成3个问题 - 在堆栈上分配(未初始化的)空间,释放空间,然后在分配时初始化/使用空间。
要在堆栈上创建(未初始化的)空间,只需从堆栈指针中减去所需的字节数。例如,要为20(4字节)整数数组分配空间,可以执行sub esp,20*4
。
要释放堆栈中的空间,请执行与分配它的操作相反的操作。例如,要释放20(4字节)整数数组的空间,可以执行add esp,20*4
。
要初始化或使用空间,您只需要确定地址即可。这可以是esp
。
例如,要分配20(4字节)整数的数组,请将数组中的第10个整数设置为0x1234567,然后释放您可以执行的数组:
sub esp,20*4
mov dword [esp+9*4],0x1234567
add esp,20*4
您可以将多个分配组合在一起。例如:
sub esp,124 + 20*4 ;Allocate space for a 20 integer array and a 124 character string
mov dword [esp+9*4 + 124],0x1234567 ;Set 10th element (being careful to skip over the space for the string)
add esp,124 ;Free space for the string
mov dword [esp+9*4],0x89ABCDEF ;Set 10th element again
add esp,20*4 ;Free space for the array
您还可以将分配与初始化相结合。例如:
push dword 3 ;Allocate "array[3]" and set it to 3
push dword 2 ;Allocate "array[2]" and set it to 2
push dword 1 ;Allocate "array[1]" and set it to 1
push dword 0 ;Allocate "array[0]" and set it to 0
mov [esp+1*4],5 ;Change "array[1]" to 5
add esp,4*4 ;Free the array
你可以混合两者。例如:
push dword 3 ;Allocate "array[3]" and set it to 3
push dword 2 ;Allocate "array[2]" and set it to 2
sub esp,2*4 ;Allocate "array[0]" and "array[1]" without initialising them
mov [esp+1*4],5 ;Change "array[1]" to 5
add esp,4*4 ;Free the array
然而,"分配期间的初始化"当尺寸与堆叠上的东西的默认大小不匹配时,会变得有点棘手。例如,如果它是一个16位整数数组,您可以这样做:
push dword (3 << 16) | 2 ;Allocate "array[3]" and "array[2]" and set them
sub esp,2*2 ;Allocate "array[0]" and "array[1]" without initialising them
mov [esp+1*2],5 ;Change "array[1]" to 5
add esp,4*2 ;Free the array
字符串只是数组(字符数组)。例如:
push dword 'n' | ('g' << 8) | ('.' << 16) | (0 << 24) ;Allocate space for last 4 chars and set them to "ng.\0"
push dword 'S' | ('t' << 8) | ('r' << 16) | ('i' << 24) ;Allocate space for middle 4 chars and set them to "Stri"
push dword 'T' | ('h' << 8) | ('e' << 16) | (' ' << 24) ;Allocate space for first 4 chars and set them to "The "
mov byte [esp+14],'!' ;Change the string from "The String.\0" to "The String!\0"
add esp,16*1 ;Free the string
请注意,大多数汇编程序提供了将字符组合成更大(例如32位)数字的简写,使事情变得更容易。例如:
push dword "ng." ;Allocate space for last 4 chars and set them to "ng.\0"
push dword "Stri" ;Allocate space for middle 4 chars and set them to "Stri"
push dword "The " ;Allocate space for first 4 chars and set them to "The "
mov byte [esp+14],'!' ;Change the string from "The String.\0" to "The String!\0"
add esp,16*1 ;Free the string
请注意,您无法执行push dword "The String."
。在这种情况下,汇编器会将字节转换为一个巨大的88位整数(使用相同的value = (char0 << 0) | (char1 << 8) | (char2 << 8*2) | (char3 << 8*3) ... | (charN << 8*N)
逻辑),并且得到的88位整数不符合push
指令的32位放在堆栈上。
您可以从其他地方的数据初始化堆栈上的字符串。例如:
section .rodata
defaultString: db "The String.", 0
.end:
section .text
sub esp,16*1 ;Allocate space for 16 characters
mov edi,esp ;edi = address of the destination string
mov esi,defaultString ;esi = address of the source string
mov ecx,defaultString.end - defaultString ;ecx = size of the string
cld
rep movsb ;Initialise the string (by copying it from defaultString)
mov byte [esp+14],'!' ;Change the string from "The String.\0" to "The String!\0"
add esp,16*1 ;Free the string
通过从只读数据复制&#34;初始化&#34;技术适用于任何大小的数组(和字符串)。