- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
为什么这段代码有效?
http://www.int80h.org/strlen/说字符串地址必须在 EDI
寄存器中才能使 scasb
工作,但这个汇编函数似乎没有这样做。
mystrlen
的汇编代码:
global mystrlen
mystrlen:
sub ecx, ecx
not ecx
sub al, al
cld
repne scasb
neg ecx
dec ecx
dec ecx
mov eax, ecx
ret
C 主:
int mystrlen(const char *);
int main()
{
return (mystrlen("1234"));
}
编译:
nasm -f elf64 test.asm
gcc -c main.c
gcc main.o test.o
输出:
./a.out
echo $?
4
最佳答案
问题中的代码是 32 位版本的 strlen,它只能在 64b 环境中部分工作,有点“偶然”(因为大多数 SW 在现实中工作,无论如何 ;))。
64b 环境的一个意外影响是(在 64b linux 操作系统使用的 System V ABI 中,其他 64b 平台可能遵循不同的调用约定,使它无效!),函数调用中的第一个参数被传递rdi
注册,scasb
在 64b 模式下使用 es:rdi
,所以这很自然地结合在一起(正如 Jester 的回答所说)。
其余的 64b 环境效果不太好,该代码将返回 4+G 长字符串的错误值(我知道,在实际使用中极不可能发生,但可以通过提供这么长的字符串的综合测试来尝试)。
修复了 64b 版本(例程结束时利用 rax=0 在单条指令中执行 neg ecx
和 mov eax,ecx
):
global mystrlen
mystrlen:
xor ecx,ecx ; rcx = 0
dec rcx ; rcx = -1 (0xFFFFFFFFFFFFFFFF)
; rcx = maximum length to scan
xor eax,eax ; rax = 0 (al = 0 value to scan for)
repne scasb ; scan the memory for AL
sub rax,rcx ; rax = 0 - rcx_leftover = scanned bytes + 1
sub rax,2 ; fix that into "string length" (-1 for '\0')
ret
关于c - 为什么 strlen 的 REPNE SCASB 实现有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42655541/
我有一个字符串,正在尝试找出它的长度。我正在使用 rw32-2017。我尝试使用 repe scasb 扫描字符串,但它根本没有改变 ZF。有没有更简单的方法来查找字符串的长度? 我的程序: %inc
我有一个字符串,正在尝试找出它的长度。我正在使用 rw32-2017。我尝试使用 repe scasb 扫描字符串,但它根本没有改变 ZF。有没有更简单的方法来查找字符串的长度? 我的程序: %inc
所以我写了一个基于NASM的程序,接收用户输入(准确的说是两个数),然后实现两个数的加减,然后打印回来。该程序在 NASM 中运行良好,但我在使用 GAS 时遇到了问题。由于段错误,使用 repne
为什么这段代码有效? http://www.int80h.org/strlen/说字符串地址必须在 EDI 寄存器中才能使 scasb 工作,但这个汇编函数似乎没有这样做。 mystrlen 的汇编代
我是一名优秀的程序员,十分优秀!