交换字符串的第一个和最后一个字符导致段错误
Swapping first and last characters of string results in seg fault
我的目标是交换 x86-assembly
中字符串 some_str
的第一个字符和最后一个字符。
这是我的尝试:
; assemble and link with:
; nasm -f elf32 -g test.asm && ld -melf_i386 test.asm.o -o test
section .text
global _start
extern printf
_start:
mov eax, some_str
_loop:
mov di, [eax + 4] ; ptr to end char
mov si, [eax] ; ptr to start char
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
mov [si], dl ; start char = end char
mov [di], al ; end char = char 1
mov edx, len
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80
ret
mov eax, 1
int 0x80
section .data
some_str db `abcd`, 0xa
len equ $ - some_str
出于某种原因,我忘记了这些台词:
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
导致程序出现段错误。
预期的标准输出是:
dbca
实际标准输出:
Segmentation fault (core dumped)`
有什么我遗漏的吗?如何更正此代码以正确交换 some_str
.
的第一个和最后一个字符
您的代码似乎在做一些比必要的复杂得多的事情。在 mov eax, some_str
之后,我们让 eax
指向要交换的字节之一,而 eax+4
指向另一个。所以只需将它们加载到两个 8 位寄存器中,然后将它们以相反的方式存储回来。
mov eax, some_str
mov cl, [eax]
mov dl, [eax + 4]
mov [eax + 4], cl
mov [eax], dl
大功告成,可以继续写出结果了。
请注意,不必先将指针加载到 eax
;你也可以
mov cl, [some_str]
mov dl, [some_str + 4]
mov [some_str + 4], cl
mov [some_str], dl
如果你真的想让两个不同的寄存器指向两个不同的字节:首先,它们需要是32位的寄存器。尝试使用 16 位寄存器 si, di
在 32 位模式下寻址内存实际上是行不通的。其次,mov edi, [eax]
会加载 edi
位置 eax
的内存内容,这是字符串的一些字节,而不是指针。您只需要 mov edi, eax
。对于第二个,您可以使用 lea
进行有效地址计算的算术运算,但保留结果指针而不是进行加载。所以我认为将您的代码变成具有原始(低效)精神但正确的东西的方法是
mov edi, eax
lea esi, [eax+4]
mov dl, [edi]
mov al, [esi]
mov [esi], dl
mov [edi], al
我的目标是交换 x86-assembly
中字符串 some_str
的第一个字符和最后一个字符。
这是我的尝试:
; assemble and link with:
; nasm -f elf32 -g test.asm && ld -melf_i386 test.asm.o -o test
section .text
global _start
extern printf
_start:
mov eax, some_str
_loop:
mov di, [eax + 4] ; ptr to end char
mov si, [eax] ; ptr to start char
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
mov [si], dl ; start char = end char
mov [di], al ; end char = char 1
mov edx, len
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80
ret
mov eax, 1
int 0x80
section .data
some_str db `abcd`, 0xa
len equ $ - some_str
出于某种原因,我忘记了这些台词:
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
导致程序出现段错误。
预期的标准输出是:
dbca
实际标准输出:
Segmentation fault (core dumped)`
有什么我遗漏的吗?如何更正此代码以正确交换 some_str
.
您的代码似乎在做一些比必要的复杂得多的事情。在 mov eax, some_str
之后,我们让 eax
指向要交换的字节之一,而 eax+4
指向另一个。所以只需将它们加载到两个 8 位寄存器中,然后将它们以相反的方式存储回来。
mov eax, some_str
mov cl, [eax]
mov dl, [eax + 4]
mov [eax + 4], cl
mov [eax], dl
大功告成,可以继续写出结果了。
请注意,不必先将指针加载到 eax
;你也可以
mov cl, [some_str]
mov dl, [some_str + 4]
mov [some_str + 4], cl
mov [some_str], dl
如果你真的想让两个不同的寄存器指向两个不同的字节:首先,它们需要是32位的寄存器。尝试使用 16 位寄存器 si, di
在 32 位模式下寻址内存实际上是行不通的。其次,mov edi, [eax]
会加载 edi
位置 eax
的内存内容,这是字符串的一些字节,而不是指针。您只需要 mov edi, eax
。对于第二个,您可以使用 lea
进行有效地址计算的算术运算,但保留结果指针而不是进行加载。所以我认为将您的代码变成具有原始(低效)精神但正确的东西的方法是
mov edi, eax
lea esi, [eax+4]
mov dl, [edi]
mov al, [esi]
mov [esi], dl
mov [edi], al