根据 cmets 中的讨论,复制字符串的基本方法是在 .bss 中声明标签并保留保存字符串副本所需的字节数。这是使用英特尔语法,因为我没有可用的 MASM。例如,您可以在 .data 中声明您的原始字符串。例如:
section .data
str_str1 db 'string one to copy', 0
section .bss
str_str2 resb 19
对于副本,将str_str1的地址加载到esi中,将str_str2的地址加载到edi中。在cx 中加载要复制的字符数,然后调用rep movsb 将cx 中指定的字节数从esi 移动到edi。例如:
section .text
global _start
_start:
xor ecx, ecx ; clear ecx
cld ; clear direction flag (read L->R)
lea esi, [str_str1] ; load str1 in esi
lea edi, [str_str2] ; load str2 in edi
mov cx, 19 ; move 19 into cx for repeat
rep movsb ; move 19 bytes from str1 -> str2
exit:
xor edi, edi ; set zero exit code
mov eax, 1 ; set int 0x80 number to 60 (0x3c hex)
int 0x80 ; call kernel
这会将str_str 复制到str_str2。然后您可以添加代码以打印它们等。Nasm 提供了一种简单的宏语言来帮助执行重复性任务,例如读取调用和写入调用(尤其是缩进、间距、打印等) nasm 语法中的完整示例是:
; Following macros simply print indents, newlines and strings to stdout
%macro indent 1
mov eax, 4
mov ebx, 1
mov ecx, tab
mov edx, %1
int 0x80
%endmacro
%macro newlns 1
mov eax, 4
mov ebx, 1
mov ecx, onln
mov edx, %1
int 0x80
%endmacro
; strn (string const) macro is overloaded to take 1 or 2 args
%macro strn 1
mov eax, 4
mov ebx, 1
mov ecx, %1
mov edx, 1
int 0x80
%endmacro
%macro strn 2
mov eax, 4
mov ebx, 1
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
section .data
nwln db 0xa
dnln db 0xa,0xa
onln times 8 db 0xa ; 8 newlines
tab times 8 db 0x20 ; 8 spaces
msg_str1 db 0xa, ' string_1: '
msg_str2 db 0xa, ' string_2: '
str_str1 db 'string one to copy', 0
section .bss
str_str2 resb 19
section .text
global _start
_start:
xor ecx, ecx ; clear ecx
cld ; clear direction flag (read L->R)
lea esi, [str_str1] ; load str1 in esi
lea edi, [str_str2] ; load str2 in edi
mov cx, 19 ; move 19 into cx for repeat
rep movsb ; move 19 bytes from str1 -> str2
; macros to print results & add newlines
strn msg_str1, 13 ; print str1 msg
strn str_str1, 19 ; print str1
strn msg_str2, 13 ; print str2 msg
strn str_str2, 19 ; print str2
newlns 2 ; print 2 newlines
exit:
xor edi, edi ; set zero exit code
mov eax, 1 ; set int 0x80
int 0x80 ; call kernel
Nasm 编译/链接
nasm -f elf -o obj/str_cpy_32.o str_cpy_32.asm
ld -m elf_i386 -o bin/str_cpy_32 obj/str_cpy_32.o
输出
$ ./bin/str_cpy_32
string_1: string one to copy
string_2: string one to copy
查看 MASM 语法差异并进行必要的更改。你应该没有理由不能完成完全相同的事情。
确定字符串大小 - 32 位
如前所述,要确定未知字符串的长度,字符串本身必须以空字符结尾,以提供要测试的结束标记字符。字符串地址放置在edi 中,然后您有效地检查每个字符是否为零(数字零,而不是字符零),长度取决于到达空终止字符所需的迭代次数:
; szstr computes the length of a string.
; edi - string address
; edx - contains string length (returned)
section .text
strsz:
xor ecx, ecx ; zero rcx
not ecx ; set rcx = -1 (uses bitwise id: ~x = -x-1)
xor al,al ; zero the al register (initialize to NUL)
cld ; clear the direction flag
repnz scasb ; get the string length (dec ecx through NUL)
not ecx ; rev all bits of negative -> absolute value
dec ecx ; -1 to skip the null-term, ecx contains length
mov edx, ecx ; size returned in edx, ready to call write
ret
当然,您不必将其用作函数,您可以将代码放在汇编程序的主体中,但由于它是您经常使用的东西,因此将其用作函数会有所帮助。