C.E*_*iss 1 unix assembly x86-64
我最近开始研究汇编代码,我正在尝试重新编码一些基本的系统函数来掌握它,我目前仍然在我的0x0上遇到了一个分段错误strchr.
section .text
global strchr
strchr:
xor rax, rax
loop:
cmp BYTE [rdi + rax], 0
jz end
cmp sil, 0
jz end
cmp BYTE [rdi + rax], sil
jz good
inc rax
jmp loop
good:
mov rax, [rdi + rcx]
ret
end:
mov rax, 0
ret
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何使用GDB调试它,我遇到的文档非常有限或难以理解.
我在C中使用以下主要测试
extern char *strchr(const char *s, int c);
int main () {
const char str[] = "random.string";
const char ch = '.';
char *ret;
ret = strchr(str, ch);
printf("%s\n", ret);
printf("String after |%c| is - |%s|\n", ch, ret);
return(0);
}
Run Code Online (Sandbox Code Playgroud)
紧跟good标签后的说明:
mov rax, [rdi + rcx]
Run Code Online (Sandbox Code Playgroud)
应该是:
lea rax, [rdi + rax]
Run Code Online (Sandbox Code Playgroud)
你完全没有使用rcx,但是rax,你需要的是那个位置的地址,而不是那个位置的值(即lea代替mov).
请注意,与零进行比较sil的典型习惯用法实际上是test sil, sil代替cmp sil, 0.那就是:
test sil, sil
jz end
Run Code Online (Sandbox Code Playgroud)
但是,如果我们查看strchr(3)手册页,我们可以找到以下内容:
char *strchr(const char *s, int c);终止空字节被认为是字符串的一部分,因此如果
c指定为'\0',则这些函数返回指向终结符的指针.
因此,如果我们希望此strchr()实现的行为与手册页中所述相同,则必须删除以下代码:
cmp sil, 0
jz end
Run Code Online (Sandbox Code Playgroud)典型的归零成语的rax寄存器既不是mov rax, 0也不是xor rax, rax,而是xor eax, eax因为它没有编码的直接零和节省一个字节对于后者.
通过上述更正和建议,代码如下所示:
section .text
global strchr
strchr:
xor eax, eax
loop:
; Is end of string?
cmp BYTE [rdi + rax], 0
jz end
; Is matched?
cmp BYTE [rdi + rax], sil
jz good
inc rax
jmp loop
good:
lea rax, [rdi + rax]
ret
end:
xor eax, eax
ret
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |