【发布时间】:2022-02-02 22:13:03
【问题描述】:
我正在尝试在 Assembly x86 中重写下面的 C 代码
int myFn( char * v, char c, int size ) {
int i;
for(i=0; i < size; i++ )
if( v[i] == c )
return i;
return -1;
}
我尝试在 x86 中使用此代码:
myFn:
mov esi, 0
mov ebx, [esp + 8]
mov ecx, [esp + 12]
FOR:
mov eax, -1
cmp esi, [esp + 4]
jge ENDFOR
cmp [ecx + esi], ebx
je EQUAL
inc esi
jmp FOR
EQUAL:
mov eax, [esi]
ENDFOR:
ret
我还创建了这个程序来测试功能:
section .data
fmt: db "strfind: %d", 10, 0
str: db "test", 0
section .text
global main
extern printf
main:
mov eax, 's'
mov ebx, 4
push str
push eax
push ebx
call myFn
add esp, 12
push eax
push fmt
call printf
add esp, 8
ret
myFn:
mov esi, 0
mov ebx, [esp + 8]
mov ecx, [esp + 12]
FOR:
mov eax, -1
cmp esi, [esp + 4]
jge ENDFOR
cmp [ecx + esi], ebx
je EQUAL
inc esi
jmp FOR
EQUAL:
mov eax, [esi]
ENDFOR:
ret
我在尝试测试时收到Segmentation Fault 错误或错误结果。我认为问题在于将字符串的字符与我要查找的字符进行比较时
【问题讨论】:
-
存在多个问题,但直接原因可能是
mov eax, [esi]。您想要mov eax, esi,因为esi是索引而不是地址。您还比较了 4 个字节而不是 1 个字节,破坏了被调用者保存的寄存器和未对齐堆栈以命名一些其他问题。 -
这里有两个比较:
cmp esi, [esp + 4]这是比较i < size并且应该是一个int大小的比较。 但是另一个cmp [ecx + esi], ebx与v[i] == c应该是char/字节大小的比较。 -
是的,所以主要问题是第二次比较,我该如何解决?
-
这是memchr;寻找 memchr 的简单示例(尽管您在搜索时找到的大部分内容都会经过高度优化)。或者查看 C 编译器的编译器输出以获取 C 代码,尽管这不会使用 NASM 语法。不过,在使用字节操作数大小时应该清楚。 How to remove "noise" from GCC/clang assembly output?