为什么 al 和 bl 和 cl 寄存器表现得很奇怪

问题描述 投票:0回答:1
section .data
    format db '%d', 0x0a, 0

section .text
    global ft_strlen

ft_strlen:
    push ebp
    mov ebp, esp

    mov ecx, [ebp + 8]
    mov eax, 0
    
    loop:
    mov cl, [ecx + eax]
    inc eax
    cmp cl, 0
    jne loop

    mov esp, ebp 
    pop ebp
    ret

当我使用 cl 寄存器时,程序正常工作,但是当我使用 al 时,它给了我一个无限循环,当我使用 bl 时,它给了我一个 SEGV。 实际上这很奇怪,因为其中三个是8位寄存器。

assembly x86 nasm
1个回答
0
投票

当我使用

cl
注册时,程序可以正常工作,但是当我使用
al
时,它会给我一个无限循环

这两个选项同样错误,但它们所产生的效果大多是巧合!

mov cl, [ecx + eax]
中,ECX是字符串的基地址,EAX是字符串的偏移量。您不应将字符串中的字节加载到 CL 中,因为 CL 是较大 ECX 寄存器的最低 8 位,同样,您不应将字节加载到 AL 中,因为 AL 是较大 EAX 寄存器的最低 8 位。

当我使用

bl
时,它会给我一个 SEGV。

一旦保留了 BL 预先存在的值(在堆栈上),使用 BL 就会成为一种选择。那是因为 EBX 需要“调用保留”。

其实很奇怪,因为其中三个是8位寄存器。

x86 架构没有单独的 8 位寄存器。我们所认为的 8 位寄存器始终是更大寄存器的一部分。

解决方案:使用另一个调用破坏的寄存器,如 EDX

ft_strlen:
  mov   ecx, [esp+4]          ; Base
  xor   eax, eax              ; Offset
.loop:
  movzx edx, byte [ecx + eax]
  inc   eax
  test  dl, dl
  jnz   .loop
  dec   eax                   ; Don't include zero-terminator
  ret

您的代码在返回的计数中包含零终止符。通常,我们不会这样做...

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