nasm x86_64中的Strcmp,寄存器



我正在尝试在asm中实现我自己的strcmp。这是ft_strcmp.s文件:

global ft_strcmp
section .text
ft_strcmp:
mov eax, [rdi]
sub eax, [rsi]
jne .exit
cmp byte [rdi], 0 ; if s1 end
je .exit
cmp byte [rsi], 0 ; if s2 end
je .exit
inc rdi
inc rsi
jmp ft_strcmp
.exit:
ret

对于第一个字母,可以:char*s1=";Hello World"char*s2=";Jdllo World";结果是1。(0000 0001(

问题是,当我试图比较这些字符串时:

char*s1=";Hello World">

char*s2=";Hdllo World";

RAX中的结果不是1,而是256。(0000 00010000 0000(

另一个例子:

char*s1=";Hello World">

char*s2=";Hcllo World">

RAX中的结果不是2,而是512。(0000 00100000 0000(

正如你已经理解的,第三个不同字母的结果将是:

char*s1=";Hello World">

char*s2=";赫克洛世界;

RAX中的结果不是1,而是65536。(0000 00010000 0000 0000(

我意识到RAX的递增是不对的,但我在代码中找不到错误。所以我请你帮我理解。

Assembly与其他语言不同,因此您认为可能发生的事情往往并不是实际发生的事情。你得到令人惊讶/不正确结果的原因是你减去了两个数字。在获得调试器(如果您想在程序集中学习/生存,则应该已经拥有调试器(之前,您不会立即看到这一点。让我们看看在调试器的帮助下发生了什么。首先,让我们设置一个小型main和一些数据:

section .data
str1: db "Hello world",0
str2: db "Hdllo world",0
section .text
global main
ft_strcmp:
... ; your code here
main:
nop
mov rdi, str1
mov rsi, str2

call ft_strcmp
nop

当执行开始时,我们用字符串(这只是一个字节序列(加载rdirsi。这里重要的是CCD_ 4和CCD_;包含";但指向它们的字符串/字节(即rdirsi(包含我们的字符串所在位置的地址。

接下来我们调用这个函数,这里是问题开始发生的地方。我将重点介绍这两条指令:

mov eax, [rdi] ;1
sub eax, [rsi] ;2

在指令1中,将字符串本身移动到eax中。[rdi]表示rdi具有的地址处获取值。这就像取消引用一个指针。现在,eax的大小是32位(4个字节(,因此它只能包含4个字节。假设您有一个litte-endian系统,字节的顺序将相反,因此eax中的值将为:

eax = 0x6c6c6548

如果你仔细观察它,你会发现它是来自str1:的4个字节

6c  6c   65  48
'l' 'l' 'e'  'h'

接下来,从rsi中地址的值中减去这个数字,即:

0x6c6c6448
OR
0x6c 6c  64  48
'l' 'l' 'd'  'h'

如果你减去这两个数字:

0x6c6c6548 - 0x6c6c6448 = 0x100

基站10中的CCD_ 16是256。

由于该值不是零,因此不会设置ZF(零标志(,您将跳转到.exit

希望你现在了解实际发生了什么。

我强烈建议您使用调试器来调试此类问题。

相关内容

  • 没有找到相关文章

最新更新