In assembler, why is the use of registers different from addition and subtraction?

I have very serious doubts. I have two very simple C codes and their assembler codes:

program 1:

main() { int temp1, temp2, temp3; char temp5, temp6, temp7, temp8, temp9; temp1 = 5; temp1 = 9 - temp1; } 

Assembly:

  0x080483b4 <+0>: push ebp 0x080483b5 <+1>: mov ebp,esp 0x080483b7 <+3>: sub esp,0x20 0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5 0x080483c1 <+13>: mov eax,0x9 0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc] 0x080483c9 <+21>: mov DWORD PTR [ebp-0xc],eax 0x080483cc <+24>: leave 0x080483cd <+25>: ret 

Program 2:

 main() { int temp1, temp2, temp3; char temp5, temp6, temp7, temp8, temp9; temp1 = 5; temp1 = 9 + temp1; } 

Assembly:

  0x080483b4 <+0>: push ebp 0x080483b5 <+1>: mov ebp,esp 0x080483b7 <+3>: sub esp,0x20 0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5 0x080483c1 <+13>: add DWORD PTR [ebp-0xc],0x9 0x080483c5 <+17>: leave 0x080483c6 <+18>: ret 

Why, in the case of subtraction, it is necessary to use the eax register, and not in the case of addition. Can not be:

 0x080483c1 <+13>: sub DWORD PTR [ebp-0xc],0x9 

instead

 0x080483c1 <+13>: mov eax,0x9 0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc] 
+7
source share
4 answers

I assume that the addition is commutative (A + B == B + A), while the subtraction is not (A - B! = B - A). Because of this, adding 9 + temp1 same as temp1 + 9 , hence a simpler assembler sequence. 9 - temp1 enables the creation of a temporary variable.

+10
source

temp1 = 9 - temp1; matches temp1 = - temp1 + 9; . This performs 2 operations:

  • Cancel temp1
  • Make an addition

eax used as a temporary location to maintain the average value.

In the additional case, there is no "average value", the operation can be performed directly.

+2
source

The actual reason for the observed behavior is implied by other answers, but has never been explicitly mentioned:

Common instruction sets contain ops functions for the following calculations:

 %register := %register + $immediate [1] %register := %register - $immediate [2] 

Because of commutativity, [1] can also be used to compute

 %register := $immediate + %register 

However, the highlighted option for

 %register := $immediate - %register 

not accessible at all, which means that it must be emulated, for example, by a sequence

 %temp := %register %register := $immediate %register := %register - %temp 
+2
source

The reason is the lack of symmetry in the x86 instruction set, which does not contain instructions for subtracting a register from a constant.

For example, an ARM instruction set contains an RSB (Reverse SuBtract) instruction for exactly this purpose.

+1
source

All Articles