# Common Logic Structures

When analyzing code, it’s important to recognize basic flow control structures.

* Remember that the decompiler may be unreliable.

Basic structures:

* If else
* Switch case
* For

## Conditional Branches (if else)

Basic control-flow instructions: move execution to a defined address if a condition is true.

* Usually, one condition is tested at a time. Complex If/else must be broken.

Assembly code is structured **as a graph with tests and execution** statements (the body of the condition).

x86 and most architectures have inherent support for many types of comparisons.

* In x86 this is the jXX family of instructions.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FjnqQRADzSzzukfxX7Qbg%2Fimage.png?alt=media&#x26;token=12e3edb2-09c5-46db-9120-ac57847e7b32" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FJvwR2fNAHhxaHyhpvslE%2Fimage.png?alt=media&#x26;token=b79772d3-b3a3-462e-a47c-74bde7bb35be" alt=""><figcaption></figcaption></figure>

* Signed comparison: `l < , le <=, g >, ge >=`
* Unsigned comparison: `b <, be <=, a >=, ae >=`
  * Below and Above.
* Equality `e`
* Every condition can be negated with `n`
* z, s, c, o, and p for ZF, SF, CF OF, and PF
  * **ZF: Zero Flag**, 1 if the last operation was 0.
  * **CF: Carry Flag.** The last operation required an additional bit (e.g. 255 + 1, which has 9 bits).
  * **OF: Overflow Flag**. The last operation had an arithmetic overflow (127 + 127 in a signed variable results in overflow).
  * **PF: Parity Flag**. 1 if the last operation resulted in a value with an even number of 1.
  * **SF: Sign Flag**. 1 if the last operation resulted in a signed value (MSB bit = 1)
* s means negative, ns non-negative.
  * Signal or not signal.
* p and np are also pe “parity even” and po “parity odd”.
* and, or, and xor clear OF and CF, and set ZF, SF, and PF based on the result.
* `test` is like `and` but only sets the flags discarding the result.
* Checking `nz` after `test` is like `if (x & mask) in C`
* `test` a register against itself is the fastest way to check for zero or negative.

**Direct jump**: target(s) specified in code (harcoded).

**Indirect jump**: target selected from runtime data like register or memory contents.

**Conditional jump**: target differs based on a condition.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2F72tP5VI2V0FijSytX4S8%2FScreenshot%20from%202024-03-27%2023-21-20.png?alt=media&#x26;token=ac895658-d4ca-4a38-93f5-fd78b6b68e4c" alt=""><figcaption></figcaption></figure>

Structure can be recognized by one or more conditional branches, without loops.

je: jump equal.

js: jump is sign.

## Switch case

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FoKbmhlhpITSdgSKHDEay%2FScreenshot%20from%202024-03-27%2023-22-25.png?alt=media&#x26;token=4541f7e2-7fed-48d6-b604-618bee3547f6" alt=""><figcaption></figcaption></figure>

A structure can be recognized by several comparisons and jumps or **jump tables**.

Observe the difference between what a programmer writes and what is produced.

* A switch is written as an atomic instruction, but it isn’t.
* Also, it is dangerous because of missing breaks.

Test: compare two registers. Set 3 flags:

* PF: Even the number of bits
* ZF: Zero
* SF: Signed value

## loops

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2Fm1dDl7WBlOHZq1bRZeVZ%2FScreenshot%20from%202024-03-27%2023-23-59.png?alt=media&#x26;token=0b06542e-394d-42c7-a8c7-b605ff20a8f1" alt=""><figcaption></figcaption></figure>

For, while and do while are generally the same.

Identified by:

* an index.
* an increment.
* a comparison.
* two jumps.
