【发布时间】:2015-03-31 03:03:52
【问题描述】:
我尝试使用 asm 重现 strcat 标准 c 函数。
这是我的 C 测试主要内容:
char *ft_strcat(char *s1, const char *s2);
int main(void)
{
char str1[60];
str1[0] = 'a';
str1[1] = '\0';
char str2[] = "poney";
printf("\n>> Test de ft_strcat <<\n\n");
printf("str1 (%p) = \"%s\"\n", str1, str1);
printf("str2 (%p) = \"%s\"\n", str2, str2);
printf("ft_strcat(str1, str2) : %p\n", ft_strcat(str1, str2));
printf("str1 (%p) = \"%s\"\n", str1, str1);
return (0);
}
还有我的汇编代码
section .text
global _ft_strcat
_ft_strcat:
mov rax, qword rdi ; save pointer address in rdi to return it later
start:
cmp [rdi], byte 0
jz next
inc rdi
jmp start
next:
cmp [rsi], byte 0
je end
mov r11, [rsi]
mov [rdi], r11
inc rdi
inc rsi
jmp next
end:
mov [rdi], byte 0
ret ; return rax
结果如下:
str1 (0x7fff5fbffb30) = "a"
str2 (0x7fff5fbffb20) = "小马"
ft_strcat(str1, str2) : 0x5fbffb30
str1 (0x7fff5fbffb30) = "aponey"
看来我的指针地址的高 32 位已经消失了。我无法解释为什么。
我知道这不仅仅是一个 printf 问题,因为如果我尝试打印字符串而不是 ft_strcat 返回的指针地址,我会得到一个段错误。
有什么想法吗?
【问题讨论】:
-
ret 8 ;从 rax 返回 8 个字节?一点也不。
-
你打算在这里使用什么调用约定?您的代码似乎没有使用堆栈框架,而 C 通常将其参数放入其中。
-
是的,实际上这个 ret 很愚蠢,我不得不删除它。它也使我的程序段错误好几次。
-
它是 intel x64,我通过 rdi 和 rsi 获取函数参数并通过 rax 返回
-
您在循环的每次迭代中移动 8 个字节。这是低效的,会导致未对齐的内存访问并访问超出源字符串和目标字符串末尾的内存。使用字节寄存器并在移动后测试
0,或使用movsb指令对rsi和rdi执行加载、存储和递增。
标签: c pointers assembly 64-bit nasm