我想将标志 UP 更改为 1,现在它是 UP = 0。我正在使用 Visual Studio 64 位程序集。
(英特尔称之为“方向标志”,DF)。
我试过这个:
.data
source DB 'Hello, world!', 0
byte_to_find DB 'o'
.code
MyProc1 proc
std ; Set Direction Flag to 1 (backward direction)
lea rdi, source ; Load address of source string
mov al, byte_to_find ; Load byte to find into AL
mov rcx, 13 ; Length of the source string
SearchLoop:
scasb ; Compare AL with byte at [RSI]
jne NotFound ; Jump if not equal (byte not found)
jmp ByteFound ; Jump if equal (byte found)
NotFound:
mov rax, 0 ; Set RAX to 0 (byte not found)
jmp Done
ByteFound:
mov rax, rdi ; Store the address of the found byte in RAX
dec rax ; Adjust RAX to point to the byte before the found byte
jmp Done
Done:
ret
MyProc1 endp
end
但是当我调试时没有任何变化,仍然是 UP = 1。之后我也尝试仅使用 std 和 mov,但出现了同样的问题。
使用
scasb
向前搜索需要将方向标志DF设置为0。cld
指令可以做到这一点。它还需要将要查找的字符加载到 AL 寄存器,并将字符串的第一个字符的地址加载到 RDI 寄存器。
使用scasb
向后搜索需要将方向标志DF设置为1。
std
指令可以做到这一点。它还需要将要查找的字符加载到 AL 寄存器,并将字符串的最后一个字符的地址加载到 RDI 寄存器。那么要使用的公式是:RDI = AddressFirstChar + LengthString - 1
如果我们计划使用 repne
前缀,我们还需要向 RCX 寄存器加载字符串的长度。你可以写:
std ; Set DF to 1 (backward direction)
mov al, byte_to_find ; Load byte to find in AL
mov ecx, 13 ; Load length of the string in RCX
lea rdi, [source + rcx - 1] ; Load address of last character in RDI
jne NotFound ; Jump if not equal (byte not found)
jmp ByteFound ; Jump if equal (byte found)
未找到:您不需要这两个跳跃。因为零标志 ZF 只有两个状态,要么是 0,要么是 1,所以如果 ZF=1,您可以跳转到NotFoundByteFound
,如果 ZF=0,则直接跳转到
。
SearchLoop:
scasb ; Compare AL with byte at [RSI]
jne NotFound ; Jump if not equal (byte not found)
jmp ByteFound ; Jump if equal (byte found)
虽然您将其命名为“SearchLoop”,但这里没有实际的循环!在
scasb
完成 AL 中的单个字节与内存中 es:[rdi]
处的字节的比较后,您立即跳转到过程中两个可能的出口之一。您需要通过在该指令前添加
scasb
前缀来重复 repne
指令(不等于时重复): repne scasb
je ByteFound
NotFound:
或者通过编写一个正常的循环:
SearchLoop:
scasb
je ByteFound
dec rcx
jnz SearchLoop
NotFound:
NotFound:
mov rax, 0 ; Set RAX to 0 (byte not found)
jmp Done
ByteFound:
mov rax, rdi ; Store the address of the found byte in RAX
dec rax ; Adjust RAX to point to the byte before the found byte
jmp Done
Done:
ret
这里需要进行一些清理,但特别值得注意的是您的评论“调整 RAX 以指向字节我不知道为什么你想返回找到之前之前找到的字节”。
之前的地址,但如果这确实是你需要的,那么就知道RDI已经指向找到的字节之前,所以你不需要那个dec rax
!如果您需要指向查找本身,您宁愿增加该值:
NotFound:
xor eax, eax ; Set RAX to 0 (byte not found)
ret
ByteFound:
lea rax, [rdi + 1] ; Set RAX to point to the found byte
ret
std ; Set DF to 1 (backward direction)
mov al, byte_to_find ; Byte to find in AL
mov ecx, 13 ; Length of the string in RCX
lea rdi, [source + rcx - 1] ; Address of last character in RDI
repne scasb
cld ; (*)
je ByteFound
NotFound:
xor eax, eax ; Set RAX to 0 (byte not found)
ret
ByteFound:
lea rax, [rdi + 1] ; Set RAX to point to the find
ret
cld