这是一个非常基本的strlen()
实现的源代码。
#include <stddef.h>
#include <stdint.h>
extern uintptr_t lx_syscall3(uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t nr);
static void lx_sys_exit(uintptr_t code)
{
lx_syscall3(code, 0, 0, 4001);
while (1);
}
static size_t lx_strlen(char const* s)
{
size_t len = 0;
while (*(s++)) {
len++;
}
return len;
}
int main() {
lx_sys_exit(lx_strlen("HELO"));
while (1);
}
syscall.s
与与此问题无关的文件一起编译,生成的 GCC 代码lx_strlen
被内联到main
(at -Os
) 中:
004004fc <main>:
4004fc: 3c1c000b lui gp,0xb
400500: 279c8154 addiu gp,gp,-32428
400504: 0399e021 addu gp,gp,t9
400508: 8f828034 lw v0,-32716(gp)
40050c: 27bdffe0 addiu sp,sp,-32
400510: 24424a64 addiu v0,v0,19044
400514: afbc0010 sw gp,16(sp)
400518: afbf001c sw ra,28(sp)
40051c: 00402825 move a1,v0
400520: 00452023 subu a0,v0,a1
# strlen loop block follows
400524: 24420001 addiu v0,v0,1
400528: 8043ffff lb v1,-1(v0)
40052c: 5460fffd bnezl v1,400524 <main+0x28>
400530: 00452023 subu a0,v0,a1
400534: 8f998118 lw t9,-32488(gp)
400538: 24070fa1 li a3,4001
40053c: 00003025 move a2,zero
400540: 04110093 bal 400790 <lx_syscall3>
400544: 00002825 move a1,zero
400548: 1000ffff b 400548 <main+0x4c>
40054c: 00000000 nop
运行时qemu-mipsel
,代码正确输出退出状态4
。所以它似乎工作正常,问题是我只是不明白它是如何工作的。注意 处的偏移-1(v0)
量400528
。所以循环总是检查存储在v0
. 因此,到零时,减去原始地址应该产生5
,而不是4
。知道它是如何工作的吗?