If it is int a = 5, b = 3, c = a / b; in the compiler, the allocation of registers is based on the activity between variables: variables that are active at the same time cannot use the same register, otherwise the data will be covering each other.

2024/05/2223:06:33 technology 1923

Because of the problem between storage speed and cost , the entire storage system of the computer can be divided into 4 levels from to , CPU, , from near to far: register , cache cache, main memory , and hard disk.

is the register closest to the CPU, and is the fastest to read and write .

The hard disk farthest from the CPU has the slowest read and write speed.

Most languages ​​​​of , including C language , are and do not need to pay attention to how the register is allocated to . This part of the work is handled by the compiler .

Of course, assembly language requires to manually allocate registers to . When

programmers write assembly, they will give a register allocation plan based on their own intuition.

For example, 5 / 3 = 1; the assembly is written like this:

mov 5, eax

xor edx, edx

mov 3, ecx

div ecx

At this time, quotient is in eax, and the remainder of is in edx. This is how the Intel CPU is designed with division instructions. The

division uses fixed registers eax and edx, which is a shortcoming of the CISC architecture , making register allocation troublesome.

If it is int a = 5, b = 3, c = a / b;

then try to allocate register eax to c, because the quotient of division defaults to in eax, which can improve the quality of the generated assembly code Efficiency .

If c = a % b, then try to allocate register edx to c, because the remainder is in edx by default. Because

only has 16 registers, when the program size is large, the registers cannot be allocated so ideally.

In the compiler , the allocation of registers is based on the activity between variables: is active in the variable of at the same time. cannot use the same register of , otherwise the data will overwrite each other. The dividend a and divisor b of in this line of code

c = a/b must be active at the same time . At the moment when the division instruction is run, must be active at the same time (and cover each other).

c is not active at the same time as a and b. It becomes active after division is run.

If the variable a no longer uses after this line of code, then c and a can share eax with .

If a is used later, eax cannot be shared. For example:

int a = 5, b = 3;

int c = a / b;

c += a; // a is still active here and cannot be overwritten when c = a / b in the second line. At this time,

can only assign eax to c. At the same time, edx is occupied by division instruction, so a and b can only use ecx and ebx. The above code of

is translated into assembly:

mov 5, ecx // a uses ecx

mov 3, ebx // b uses ebx

mov ebx, eax // loads the lowest 32 bits of the dividend to eax

xor edx, edx // the high 32 of the dividend Bit cleared

div ebx // The real division operation is just this one

add ecx, eax // c += a

If it is int a = 5, b = 3, c = a / b; in the compiler, the allocation of registers is based on the activity between variables: variables that are active at the same time cannot use the same register, otherwise the data will be covering each other. - DayDayNews

The register conflict diagram of the above 2 lines of code c = a / b, c += a, as above.

colors the 3 vertices a, b, and c of this graph . The two vertices of connected by the conflict line cannot be the same color of , that is, cannot allocate the same register .

Because CISC uses edx for division, we also add it as a constraint to this figure: variable a cannot use it because it will be overwritten by the remainder of the division operation of , and a is at c += a Lines of code still need to be used.

c can use it, but c as the quotient of division operation should give priority to eax, otherwise one more assembly code of mov eax and edx will be needed. Byte allocation of

If it is int a = 5, b = 3, c = a / b; in the compiler, the allocation of registers is based on the activity between variables: variables that are active at the same time cannot use the same register, otherwise the data will be covering each other. - DayDayNews

64-bit register

The actual CPU register is a 64-bit register group . The relationship between its lowest 8 bits AL, the next lowest 8 bits AH, the lowest 16 bits AX, the lowest 32 bits EAX, and the entire register RAX is as follows picture.

al conflicts with rax:

char buf[8] = {0};

char c = 'A';

char* p = buf;

*p += c;

If the pointer p uses rax, then the char type variable c can no longer use al, and vice versa. In the

code *p += c, the pointer variable p and the character variable c are active at the same time. This situation of

can be judged by the mask . You can use 1 binary -bit to represent the 1 bytes of the register :

1. RAX is an 8-byte register, and the mask is 0xff.

2, al is a 1-byte register, and the mask is 0x1.

3, the mask of ah is 0x2 because it uses the second byte of .

4, the mask of ax is 0x3, 2 bytes.

5, the mask of eax is 0xf, 4 bytes.

If the masked and operation are not 0, they are conflicting registers and cannot be used for the same variable.

Of course, is not a register of the same register group , and there is definitely no conflict.

ah and al do not conflict because 0x2 & 0x1 == 0.

ah conflicts with ax because 0x2 & 0x3 != 0.

If it is int a = 5, b = 3, c = a / b; in the compiler, the allocation of registers is based on the activity between variables: variables that are active at the same time cannot use the same register, otherwise the data will be covering each other. - DayDayNews

technology Category Latest News