为什么 strcmp 的这个汇编实现会表现出意外?

问题描述 投票:0回答:1

我一直在 x86_64 程序集中编写自己的 strcmp 函数的简单实现。
我编写了一个 C 测试程序来将其行为与 C 库中的真实 strcmp 进行比较。
即使两个函数似乎返回相同的值,条件

(strcmp(s1,s2) == my_strcmp(s1,s2))
好像是假的。
奇怪的是,
my_strcmp(s1,s2) == strcmp(s1,s2)
似乎是真的。 我错过了什么?

在排除故障时,我用 C 语言的 strcmp 实现和相同的测试程序进行了编译,只是为了验证: 效果很好,所有行为都是预期的。

my_strcmp.s:

; Function: int my_strcmp(const char *dest, const char *src);
; Arguments:
;       rdi             s1
;       rsi             s2
; Variable:
;       rcx             counter
; Returned value :

section .text
global my_strcmp

my_strcmp:
    ; Function prologue (optional)
    push rbp
    mov rbp, rsp

        xor rcx,rcx
loop:
        mov al, byte [rdi]
        mov bl, byte [rsi]
        cmp al, bl
        jne not_equal
        test al,al
        je null_byte_found
        
        inc rdi
        inc rsi
        jmp loop

not_equal:
        sub al, bl      
        movsx rax, al 
        jmp end
null_byte_found:
        xor rax,rax
        jmp end
end:
    ; Function epilogue (optional)
    mov rsp, rbp
    pop rbp
        ret

main.c(测试程序):

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
extern int my_strcmp(const char *s1, const char *s2);

void    test_my_strcmp();

int main() {
        test_my_strcmp();
    return 0;
}

void    test_my_strcmp(){
        char s1[10] = "123456789";
        char s2[10] = "12345AAA";
        int a = strcmp(s1,s2);  
        int b = my_strcmp(s1,s2);       
        if ( a == b)
                printf("a == b\n");
        if (strcmp(s1,s2) == -11)
                printf("strcmp return value is -11\n");
        if (-11 == my_strcmp(s1,s2))
                printf("my_strcmp retun value is -11\n");
        if (strcmp(s1,s2) == my_strcmp(s1,s2))
                printf("OK1\n");
        if (my_strcmp(s1,s2) == strcmp(s1,s2))
                printf("OK2\n");
}

my_strcmp.c(只是为了验证):

int my_strcmp(const char *s1, const char *s2){
        while (*s1 && *s2 && (*s1 == *s2))
        {
                s1++;
                s2++;
        }
        return (*s1 - *s2);
}

构建步骤/重现错误

创建 3 个文件后

my_strcmp.s
my_strcmp.c
main.c

nasm -f elf64 -g my_strcmp.s -o my_strcmp_assembly.o
gcc -c my_strcmp.c
gcc main.c my_strcmp.o -o c_version.out
gcc main.c my_strcmp_assembly.o -o asm_version.out
./c_version.out && ./asm_version.out

C 版本输出(预期输出)

a == b
strcmp return value is -11
ft_strcmp retun value is -11
OK1
OK2

asm版本输出

a == b
strcmp return value is -11
ft_strcmp retun value is -11
OK2

gcc版本:11.4.0(最新) nasm 版本:2.15.05(最新)

``

c x86 x86-64
1个回答
0
投票

您正在使用

%bl
作为临时寄存器。

  1. 该寄存器归 calling 函数所有(即 不是 你的)。
  2. 这个必须由您为函数的调用者保留。
  3. 在函数序言/结尾期间推入/弹出
    %rbx
    或使用其他寄存器。

请参阅:https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf的第 3.2.1 节,了解寄存器列表以及调用者/被调用者如何使用它们

© www.soinside.com 2019 - 2024. All rights reserved.