2015-03-31 138 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