|
10 | 10 | _strlcpy: |
11 | 11 |
|
12 | 12 | ld iy, 0 |
| 13 | + lea bc, iy ; set bc to 0 |
13 | 14 | add iy, sp |
14 | 15 |
|
15 | 16 | ; do min(strlen(src), dsize-1) |
16 | 17 |
|
17 | 18 | ; strlen(src) |
18 | 19 | ld hl, (iy + 6) ; hl = pointer to src |
19 | | - xor a,a ; clear carry and set a to 0 |
20 | | - ld bc, 0 |
| 20 | + xor a, a ; clear carry and set a to 0 |
21 | 21 | cpir ; dec bc until byte at (hl) matches a (= NUL) |
22 | 22 | ; calculate HL=-BC-1 |
23 | | - sbc hl,hl |
| 23 | + sbc hl, hl |
24 | 24 | scf |
25 | | - sbc hl,bc |
| 25 | + sbc hl, bc ; always sets carry flag |
26 | 26 | ; now hl = strlen(src) |
27 | 27 |
|
28 | 28 | push hl ; save this for after dsize check |
29 | 29 |
|
30 | 30 | ld bc, (iy + 9) ; bc = dsize |
| 31 | + ex de, hl ; de = strlen(src) |
31 | 32 |
|
32 | 33 | ; check if dsize is zero |
33 | | - xor a,a ; clear carry and set a to 0 |
34 | | - sbc hl, hl |
35 | | - sbc hl, bc |
36 | | - jr z, .strlcpy_done ; do nothing if dsize is zero |
| 34 | + sbc hl, hl ; set hl to -1, carry was already set |
| 35 | + add hl, bc ; hl = -1 + dsize |
| 36 | + jr nc, .strlcpy_done ; do nothing if dsize is zero |
37 | 37 |
|
38 | | - dec bc ; bc = dsize - 1 |
| 38 | + ; dsize is not zero, compare them |
| 39 | + ; hl = dsize - 1 |
| 40 | + ; de = strlen(src) |
39 | 41 |
|
40 | | - ; restore hl without changing the stack |
41 | | - pop hl ; get it back |
42 | | - push hl ; save it for the end |
| 42 | + ; carry flag is set, so calculate hl - (de + 1) |
| 43 | + sbc hl, de |
43 | 44 |
|
44 | | - ; dsize is not zero, compare them |
45 | | - ; hl = strlen(src) |
46 | | - ; bc = dsize - 1 |
47 | | - |
48 | | - ; https://www.msx.org/forum/development/msx-development/how-compare-16bits-registers-z80 |
49 | | - or a ; clear carry flag |
50 | | - sbc hl, bc |
51 | | - add hl, bc |
52 | | - |
53 | | - ; if hl >= bc, c = 0; keep bc as is |
54 | | - ; if strlen(src) >= (dsize - 1), c = 0; keep bc as is |
55 | | - jr nc, .ready_for_ldir |
56 | | - |
57 | | - ; hl < bc, so strlen(src) < (dsize - 1); set bc to the value in hl |
58 | | - push hl |
| 45 | + ; if hl <= de, (dsize - 1) <= strlen(src); keep bc as dsize |
| 46 | + jr c, .ready_for_ldir |
| 47 | + |
| 48 | + ; hl > de, so (dsize - 1) > strlen(src); set bc to strlen(src) + 1 |
| 49 | + push de |
59 | 50 | pop bc |
| 51 | + inc bc |
60 | 52 |
|
61 | 53 | .ready_for_ldir: |
62 | 54 | ld de, (iy + 3) ; put dst in de |
63 | | - |
64 | | - ; check if bc is zero |
65 | | - xor a,a ; clear carry and set a to 0 |
66 | | - sbc hl, hl |
67 | | - sbc hl, bc |
68 | | - jr z, .null_terminate ; null terminate if bc is zero |
69 | | - |
70 | 55 | ld hl, (iy + 6) ; put src in hl |
71 | | - ; bc is filled already |
| 56 | + ; bc is filled already and greater than 0 |
72 | 57 |
|
73 | 58 | ; at this point we are set up for an ldir: |
74 | 59 | ; hl has the start address |
75 | 60 | ; de has the destination address |
76 | | - ; bc has the length |
77 | | - |
| 61 | + ; bc has the length (including space for null terminator) |
78 | 62 | ldir |
79 | 63 |
|
80 | | -.null_terminate: |
81 | | - ; dsize is nonzero, null terminate dst |
82 | | - xor a,a ; clear carry and set a to 0 (= NUL) |
| 64 | + ; replace final byte with NUL, in case src null terminator wasn't reached |
| 65 | + dec de |
| 66 | + ; a is already 0 |
83 | 67 | ld (de), a ; store null terminator at the address pointed to by de |
84 | 68 |
|
85 | 69 | .strlcpy_done: |
|
0 commit comments