Rate This Document
Findability
Accuracy
Completeness
Readability

Bit Operations

  • Basic bit operation instructions

    The following table lists the mapping between common bit operation functions and instruction types. The derivative instructions of a specific function type are not described in this document. For details, see the Armv8 instruction manual.

    Function

    Instruction/Instruction Family

    And

    AND

    Or

    ORR

    Negation

    NEG

    Exclusive or

    EOR

    Logic shift left

    LSL

    Logic shift right

    LSR

  • Alignment judgment and processing

    As we mentioned in section 3, assembly code involves frequent memory operations. Compared with HLL, assembly code, especially the string series, focuses more on memory address alignment. The general principle of memory addressing is that only some types of addresses can be directly accessed. Other addresses can be accessed by adding offsets to the addresses that can be directly accessed. Therefore, for memory operations, directly operating the memory with aligned addresses is better than operating the memory with unaligned addresses.

    The implementation of address alignment is not complex. The key is to perform bit operations on the memory addresses. You can use the BIC instruction. However, after an address is aligned, you need to adjust related parameters to ensure that the logic is correct. In this case, the AND instruction needs to be used to calculate and save the number of bytes to be offset for address alignment. In addition, the effect of aligning addresses by using the SUB instruction is the same as that of the BIC instruction, as shown in the following code.

    /* Assume the src is the addr to be aligned */ 
    ... ...
    and         tmp, src, 15
     bic      src, src, 15 
     (sub        src, src, tmp) 
     add         count, count, tmp 
     sub        dst, dst, tmp 
    ... ...
  • Use of magic numbers

    In the source code of string functions, some specially designed magic numbers involve advanced bit operations. These magic numbers and corresponding bit operations can also be used to implement some powerful functions. For example, strcpy uses magic numbers to determine whether each byte is a null terminator.

    #define REP8_01 0x0101010101010101
    #define REP8_7f 0x7f7f7f7f7f7f7f7f
    ... ...
    ldp    data1, data2, [src], #16 
    sub   tmp1, data1, #REP8_01
    orr    tmp2, data1, #REP8_7f
    sub   tmp3, data2, #REP8_01
    orr    tmp4, data2, #REP8_7f
    bic    has_nul1, tmp1, tmp2 
    bics  has_nul2, tmp3, tmp4 
             ccmp         has_nul1, #0, #0, eq         /* NZCV = 0000  */

In the assembly code in strcpy.S, the magic numbers REP8_01 and REP8_7f are set, and the bit operation expression ((X - 1) & ~(X | 0x7f)) is used to determine whether each byte is a null terminator (0x00). The expression implementation is not described here. You can assume that a string of ASCII values is used in the expression for calculation. You will find that different calculation results are displayed only when the value is 0x00.

Another magic number appears in the implementation of memchr.S. By defining the magic number 0x40100401 and related bit calculation operations, the function of finding characters with the same ASCII value is implemented.