2015-03-31 142 views
0

我尝试使用asm重现strcat标准c函数。汇编:返回64位指针地址(nasm unix x64)

这里是我的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)=“poney”

ft_strcat(STR1,STR2):0x5fbffb30

STR1(0x7fff5fbffb30)= “aponey”

似乎我的指针地址的高32位已经消失。我无法解释为什么。

我知道这不仅仅是一个printf问题,因为如果我尝试从ft_strcat返回打印字符串而不是指针地址,则会出现段错误。

有什么想法?

+0

ret 8;从rax返回8个字节?一点也不。 – 2015-03-31 03:49:30

+0

你打算在这里使用什么调用约定?你的代码似乎没有使用堆栈框架,并且C通常将其参数放入其中。 – 2015-03-31 03:50:28

+0

是的,实际上这个ret是愚蠢的,我不得不删除它。它也使我的程序段错误多次。 – 2015-03-31 03:53:09

回答

0

好吧,我的坏,这不是一个ASM问题。我通过在我的main的顶部添加#include“libfts.h”来解决这个问题。

没有函数的原型,我想也没有办法,如果函数返回1首或8个字节的程序可以告诉..

在这一行:

MOV RAX,四字RDI

四字是不需要的,因为从/到64位寄存器的移动将已经复制8个字节

我还将compilator标志添加到我的Makefile以防止这种错误。

+0

你发布的代码没有问题;-) – chqrlie 2015-03-31 04:36:07

+0

是的愚蠢的错误。无论如何感谢您的建议 – 2015-03-31 05:10:21

0

的错误是在这里:

mov rax, qword rdi ; save pointer address in rdi to return it later 

我想这应该是:

mov rax,rdi ; save pointer address in rdi to return it later 

此外,我认为主要的循环应该改写这样的(不是最佳的,因为它进入一个字符时间,但鉴于你在每个循环中增加rsirdi一次,我认为这是你打算做的):

next: 
    cmp byte [rsi],0 
    je end 
    mov cl,[rsi] ;load 8 bits 
    mov [rdi],cl ;store 8 bits 
    inc rdi 
    inc rsi 
    jmp next 
+0

我加了qword来试图强制大小,但我自己回答,我是一个C函数原型问题。 – 2015-03-31 04:06:27

+0

你的意思是我的代码每次复制8个字符?它可以导致任何段错误? – 2015-03-31 04:11:26

+0

@Rox Teddy:访问超出数组边界的内存肯定会调用未定义的行为。如果目标数组的长度至少比源字符串长6个字节,则会覆盖内存中的其他内容。即使在字符串末尾读取内存也会调用未定义的行为。 – chqrlie 2015-03-31 04:40:03