LWN.net Logo

strncpy

strncpy

Posted Aug 21, 2003 15:08 UTC (Thu) by paulsheer (guest, #3925)
Parent article: Kernel release status


on the x86 it is not obvious what he means:

strncpy:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 16(%ebp), %ecx
movl 8(%ebp), %edx
movl 12(%ebp), %ebx
testl %ecx, %ecx
je .L8
.p2align 4,,7
.L6:
movb (%ebx), %al
movb %al, (%edx)
testb %al, %al
je .L5
incl %ebx
.L5:
incl %edx
decl %ecx
jne .L6
.L8:
popl %ebx
movl 8(%ebp), %eax
popl %ebp
ret

One can see that, in theory, one could do
something like

while (count) {
unsigned char c;
c = *tmp = *src;
c--;
"subc src, -1"
tmp++;
count--;
}

which would work on any architecture.
one of the deficiencies of C (and most (all?)
compiler languages) is that you do not have
direct access to the carry bit.

on the ARM however gcc shines:

strncpy:
cmp r2, #0
mov ip, r0
moveq pc, lr
.L6:
ldrb r3, [r1, #0] @ zero_extendqisi2
cmp r3, #0
addne r1, r1, #1
subs r2, r2, #1
strb r3, [ip], #1
bne .L6
mov pc, lr

-paul


(Log in to post comments)

strncpy

Posted Aug 21, 2003 17:29 UTC (Thu) by iabervon (subscriber, #722) [Link]

He did qualify it with "his gcc", which probably has "addl %ebx, %eax" (or whatever that should be; I don't actually know x86 assembly).

I'm not sure why he doesn't have:

src += ((*tmp = *src) != '\0');

though, which is equivalent (since a true relation is defined to evaluate to 1), and doesn't need a clever compiler to skip the branch. Of course, this line would need an explanation for those who haven't read the thread. At least this makes it obvious how many characters are written to the destination string...

strncpy

Posted Aug 21, 2003 20:09 UTC (Thu) by chad.netzer (subscriber, #4257) [Link]

I noticed the same thing as you, until a Google search led me to try it on PPC linux. And indeed, there, it does seem to save a branch. I'll post the code below. The first function, is Erik Andersen's code, which I called 'strncpy2'. The original (below it) is called 'strncpy'.

        .file   "strncpy.c"
        .section        ".text"
        .align 2
        .globl strncpy2
        .type   strncpy2, @function
strncpy2:
        mtctr 5
        mr 9,3
        cmpwi 0,5,0
        beqlr- 0
.L16:
        lbz 0,0(4)
        stb 0,0(9)
        neg 0,0
        srwi 0,0,31
        add 4,4,0
        addi 9,9,1
        bdnz .L16
        blr
        .size   strncpy2, .-strncpy2
        .align 2
        .globl strncpy
        .type   strncpy, @function
strncpy:
        mr 9,3
.L20:
        cmpwi 0,5,0
        addi 5,5,-1
        beq- 0,.L21
        lbz 0,0(4)
        stb 0,0(3)
        addi 4,4,1
        addi 3,3,1
        cmpwi 0,0,0
        bne+ 0,.L20
.L21:
        mr 3,9
        blr
        .size   strncpy, .-strncpy
        .ident  "GCC: (GNU) 3.3.2 20030812 (Debian prerelease)"

strncpy

Posted Aug 21, 2003 21:49 UTC (Thu) by armcc (subscriber, #5827) [Link]

> one of the deficiencies of C (and most (all?)
> compiler languages) is that you do not have
> direct access to the carry bit.

Could be a problem for architectures (e.g. MIPS) which don't have one :-)

(Actually, the MIPS architecture was designed around C, so if C had given carry bit access from the start maybe MIPS wouldn't have the problem...)

Copyright © 2008, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds