我正在尝试在程序集中反转字符串。 但是我的代码似乎无法正常工作。 我添加了换行符字符串以提高可读性。
我使用linux和nasm作为编译器。
我认为如果我采用地址指针的值并将它们切换到正确的位置,那么字符串最终会被反转然后恢复正常。
这是我的代码:
section .data
hello db 'Hello world!'
helloLen equ $-hello
derp db '=========',10
derplen equ $-derp
section .text
global main
main:
mov eax,0
mov ecx,helloLen
reverse:
;move pointer
mov ebx,hello
add ebx,eax
push eax
;move pointer
mov eax,hello
add eax,ecx
push ecx
;switch bytes
push ebx
mov ebx,[ebx]
mov [eax],ebx
pop ebx
mov eax,[eax]
mov [ebx],eax
;print text
mov eax,4
mov ebx,1
mov ecx,hello
mov edx,helloLen
int 80h
;Print newline
mov eax,4
mov ebx,1
mov ecx,derp
mov edx,derplen
int 80h
;increment and decrement
pop ecx
dec ecx
pop eax
inc eax
cmp eax,helloLen
jne reverse
end:
mov eax,1
mov ebx,0
int 80h
这是我得到的输出:
Hello world!Hell=====
Hello worldellol=====
Hello worlllo ol=====
Hello worlo w ol=====
Hello woo wow ol=====
Hello wooooow ol=====
Hello wooooow ol=====
Helloooooooow ol=====
Helloooooooow ol=====
Helooowooooow ol=====
Heoow wooooow ol=====
How o wooooow ol=====
答案 0 :(得分:5)
通过交换字符来反转字符串的方法是交换第一个和最后一个,然后是第二个和倒数第二个等。在C中,你会写:
for (i = 0; i < len/2; ++i)
{
c = s[i];
s[i] = s[len-i-1];
s[len-i-1] = c;
}
在汇编语言中,最简单的方法是设置ESI和EDI寄存器以指向字符串的开头和结尾,然后循环。在每次迭代时,您都会增加ESI并减少EDI。结果看起来像这样:
mov ecx, helloLen
mov eax, hello
mov esi, eax ; esi points to start of string
add eax, ecx
mov edi, eax
dec edi ; edi points to end of string
shr ecx, 1 ; ecx is count (length/2)
jz done ; if string is 0 or 1 characters long, done
reverseLoop:
mov al, [esi] ; load characters
mov bl, [edi]
mov [esi], bl ; and swap
mov [edi], al
inc esi ; adjust pointers
dec edi
dec ecx ; and loop
jnz reverseLoop
答案 1 :(得分:0)
当我接受采访时,我想出了这个......这有点像微软特有的,但它与@Jim Mischel编写的大致相同,不过这会计算字符串的长度而不是传递它等。
这个函数是裸的,所以既然没有prolog或epilog,你必须要小心你可以使用哪些寄存器。 (除非你使用它们进行推送和弹出。在这个例子中,我没有使用任何需要保存的寄存器)
#define USE_STRLEN 0 ; Use strlen to find string length?
__declspec(naked) uint8_t* string_rev(uint8_t* s)
{
__asm
{
mov eax, dword ptr[esp + 4] ; Get the address of string
test eax, eax ; Been passed a null pointer?
jz lp_3
#if (USE_STRLEN)
push eax ; Push string address onto stack
call strlen
pop ecx ; Pop our string back off the stack
xchg ecx, eax ; String length in eax
#else
or ecx, 0ffffffffh ; Start ecx at -1
lp_1:
inc ecx
test byte ptr[eax + ecx], 0ffh ; Test string byte for zero
jnz lp_1 ; ecx = string length
#endif
lea edx, dword ptr[eax + ecx - 1] ; edx = last character in string
and ecx, -2 ; Is string 1 character or less?
jz lp_3
lp_2:
mov cl, byte ptr[edx]
mov ch, byte ptr[eax]
mov byte ptr[eax], cl
mov byte ptr[edx], ch
inc eax
dec edx
cmp edx, eax ; Loop whilst one pointer is less
ja lp_2 ; than the other (equiv. len/2)
lp_3:
ret ; Reversed string in eax
}
}