; int memcmp(uint8_t* a, uint8_t* b, size_t count); ; Compares two memory segment of equal length lexicographically. ; Temporarily modifies the byte at address `a + count`. ; ; Arguments: ; - `r1`: A pointer to the first memory segment. ; - `r2`: A pointer to the second memory segment. ; - `r3`: The size of both memory segments. ; Results: ; - `r1`: ; - `0` if both segments are equal. ; - `<0` if the first segment is less than the second segment. ; - `>0` if the first segment is greater than the second segment. pub fn_memcmp: ; Exclusive end point of the second segment. add r4, r3, r2 ; Exclusive end point of the first segment. add r3, r3, r1 load_8 r6, [r3] load_8 flags, [r4] ; Check if the first bytes behind the sequences are equal. cmp flags, r6 jne _memcmp__loop ; Change the byte directly behind the first segment. xor r4, r6, 1 ; This would be problematic if someone calls memcmp with a first segment ; whose end point overlaps the program memory of this function. store_8 [r3], r4 _memcmp__loop: load_32 r4, [r1] add r1, r1, 4 load_32 r5, [r2] add r2, r2, 4 ; Comparing two sequences of 4 bytes lexicographically is equivalent to ; comparing the corresponding big endian 32 bit words. cmp r4, r5 je _memcmp__loop ; We overshot in the loop; decrement r1 again. (Only by 2, we backtrack the rest if necessary later) sub r1, r1, 2 ; Restore the byte we changed. store_8 [r3], r6 ; We encountered two different words. Figure out what byte they differ on. xor r4, r4, r5 ; Store the flags for later, to figure out the return value. mov r5, flags ; Check if at least one of the two most significant bytes is not 0. cmp r4, 0xffff jbe _memcmp__low2 ; If it is, backtrack the remaining 2 indices. ; Shift the most significant bytes to the least significant ones. sub r1, r1, 2 lsr r4, r4, 16 _memcmp__low2: ; r1 now points to a non-zero 16 bit value. ; If the 16 bit value at r1-2 is in-bounds, then it is 0. ; Check if the most significant byte of the 16 bit value is 0. cmp r4, 0xff ja _memcmp__low1 ; If it is, our target is the least significant byte. add r1, r1, 1 _memcmp__low1: ; Otherwise, the target is that non-zero byte. ; Check if the target is out of bounds, i.e. the loop terminated through the "bounds check". cmp r1, r3 jae _memcmp__oob ; r5 is the comparison result in the format of `cmp`. Convert it to the desired format. ; 00 => 0x40000000 > 0 ; 01 => 0x00000000 = 0 ; 10 => 0xC0000000 < 0 xor r1, r5, 1 lsl r1, r1, 30 jmp r13 _memcmp__oob: mov r1, 0 jmp r13