if...else if...else multi-branch structure

0 17
if 流程控制语句if control flow statementThe function of the if statement is to compare...

if 流程控制语句

if control flow statement

The function of the if statement is to compare the operation conditions first, and then execute the corresponding statement according to the comparison result

  • if...else if...else multi-branch structure

    The if statement can only judge two conditions:

  • 0 is false

non-zero is true

#include <stdio.h>

int main(int argc,char** argv)
{
if (argc == 0)
{
printf("argc == 0");
}
return 0;
}

assembly

1669265781_637ef9751f61c7e8433a9.png!small?1669265777476

RegardingifThe part implemented in assembly for the judgment is:

115c: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
if statement

1160:       75 14                 jne   1176 <main+0x2d> has already been executedargcthroughediputs the valuerbp-0x4into

  • puts the value in the stack space at the address

    cmp DWORD PTR [rbp-0x4],0x0CMPinstruction, usingrbp-0x4at the address4is0subtraction, and affects the flag bit, since the byte data afterjneAttention is paid toZFflag bit, so here it is explainedCMPonZFThe influence of the flag bit:

    • result = 0 thenZF = 1

  • jne 1176 <main+0x2d>

    • Thenthen jump, that is, ifargc != 0then jump toreturn 0;(mov eax,0x0The statement in

    • otherwise continue to executeifThe statement in

It can be found that the logic of processing is:if it does not meetifThe judgment statement jumps, if it meets the condition, it continues to execute, which is obviously different fromCThe logic of the language is the opposite:

This is due toCLanguage decides the address of the binary code compiled after the code line position, which is convenient for using labels to subtract to get the length of the code, so CThe compiler of the language cannot arbitrarily change the order of code lines in memory, soifThe priority does not meet the jump judgment, if it meets, you can execute downwards directly

So based on this characteristic, if the judgment statement isargc > 01cmpThe condition of the jump statement following it should beargc <= 0The

1669265647_637ef8ef38b41e3521319.png!small

RegardingifThe part implemented in assembly for the judgment is:

115c: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
1160:  7e 14                  jle  1176 <main+0x2d>
  • jle 1176 <main+0x2d>

    ZF = 1 || SF != OFThen the jump is performed (jleLess than or equal to jump (ifleftOp ≤ rightOp)))

if...else statement

#include <stdio.h>

int main(int argc,char** argv)
{
if (argc == 0)
{
printf("argc == 0");
}
else
{
printf("argc != 0");
}
return 0;
}    

assembly

1669265877_637ef9d558df2edfedc97.png!small?1669265874034

Regardingif...elseThe part implemented in assembly for the judgment is:

115c: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
1160:  75 16                  jne  1178 <main+0x2f>
......
......
1176:  75 14                  jmp  118c <main+0x43>

if...elseThe initial comparison and jump process is similar to the singleifThey are consistent, the only difference being1176linejmpThe statement, since after executingifThe statements after the statements inelseThe statements inside, so ajmpJump toelseThe statement after

Therefore, when restoring assembly code, if there is the above3The combination of assembly instructions, can be preliminarily judged to existif...elseStatement, andjmpThe position is located in the source codeifThe end of the statement block andelseThe beginning of the statement block

if...else statements under O1 optimization

InO1under optimization,if...elseThe optimization of branch statements in assembly is very interesting, still the above code, if you add-O1Optimization (O2is similar), then the assembly code is

1669265905_637ef9f1c1813936182e6.png!small?1669265902221

Regardingif...elseThe part implemented in assembly is very clever, let's look step by step, first is:

1151:       85 ff                 test   edi,edi        
1153:  75 20                  jne  1175 <main+0x2c>

Since our code is comparingargc == 0So here, the code to push0Pushed onto the stack and then executed throughcmpandediInargcThe value for comparison

Instead, it uses directlytestCommand,edi(argcThe value in parentheses is bitwise ANDed with itself:

  • argc == 0argc == 101ZF = 1Will not passjneInstead of jumping, it continues to execute downwardsifCode in the statement block

  • Ifargc == 1Then the bitwise AND operation still remains1ThenZF = 0if, so it is said thatjneThe condition is not met, go toelseto

code executionifThe most wonderful place here is that, in theelseInstruction block in the middle of the statement block did not see the just mentionedjmpInstruction at the end, instead of seeing theretInstruction, but found ajmpUsed to jump back toretInstruction address

So the logic at this time becomes:

  • Firstly, judge whether the condition is metifthe condition

    • satisfy: Then execute downwards, since the code in this code exceptif...elsethe statement block outside, there is no other code, so execute to1174line, directly throughretreturn directly

    • Not met:jneJump toelsein the statement block

  • execution ofelseafter the statement block, through the lastjmpJump to the statement located1174lineretreturn directly

if...else if...else multi-branch structure

#include <stdio.h>


int main(int argc,char** argv)
{
 if (argc > 0 )
{
     printf("argc > 0");
}
 else if (argc == 0)
{
     printf("argc == 0");
}
 else
{
     printf("argc <= 0");
}

return 0;
}

assembly

1669265984_637efa402d981b80bf6e0.png!small?1669265980700

As can be seenifandelse ifThe logic is the same, all throughcmp/testAfter the judgment, if the conditions are not met, follow the jump statement, although they are combined together, eachifandelse...ifIt is independent

  • if (argc > 0 )

    115c: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
    1160: 7e 16 jle 1178 <main+0x2f>
    ; Jump if less than or equal
  • else if (argc == 0)

    1178: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
    117c: 75 16 jne 1194 <main+0x4b>
    ; Jump if not equal
  • jmpJump statement

    1176: eb 30 jmp 11a8 <main+0x5f>
    ......
    1192: eb 14 jmp 11a8 <main+0x5f>
    ; Prevent re-execution of else after executing if or if...else

if...else if...else under O1 optimization

1669266016_637efa60487922340f9f2.png!small?1669266012780

InO1Under optimized conditions

1151:       85 ff                 test   edi,edi
1153:       7f 1a                 jg     116f <main+0x26>
1155:       75 38                 jne   118f <main+0x46>

Here, it may not be what is said, it seems that we do not know what it wants to do, but if we look carefully, the position of the string we want to output has been changed, and the structure of the current assembly code has changed

  • 1157 - 1168The line corresponds to the case where the condition is metelse if (argc == 0)The statements to be executed

  • 116f - 1180The line corresponds to the case where the condition is metif (argc > 0 )The block of statements to be executed

  • 118f - 11a0The line corresponds to the case where none of the conditions are metelseThe block of statements to be executed

So throughjg 116f <main+0x26>Judgment if> 0Then jump directly to116f ifat

If not satisfied, then throughjne 118f <main+0x46>Judgment if!= 0, as indicated by the previous judgment, it is not greater than0So jump to118f elseat

Otherwise== 0Then executeelse if (argc == 0)

By changing the order of the statements, only one judgment instruction test is used to complete the jump judgment for all conditions

你可能想看:
最后修改时间:
admin
上一篇 2025年03月30日 03:09
下一篇 2025年03月30日 03:32

评论已关闭