Secure coding

How to implement common logic constructs such as if/else/loops in x86 assembly

February 17, 2021 by Srinivas

In the last few articles on x86 assembly, we discussed a variety of concepts which include x86 Instruction Set Architecture, x86 syntax types, data representation, commonly used x86 instructions, building x86 assembly programs by assembling and linking, using gdb to debug the programs, the use of tools like ObjDump, segmentation faults and control flow instructions.

This article covers the logical instructions supported in x86 assembly. Some of the logical instructions such AND, OR and XOR also have an effect on conditional flags like ZF and PF. So, we will also discuss how these logical instructions can also be used to control the flow of the program.

Programming with logical instructions in x86 assembly

The logical instructions perform basic logical operations on their operands. The following table illustrates the mnemonics used in x86 assembly when writing assembly programs.

Mnemonic Description
AND Bitwise logical AND
OR Bitwise logical OR
XOR Bitwise logical exclusive OR
NOT Bitwise logical NOT

While the first three instructions (AND, OR, XOR) in the preceding table perform binary operations, the NOT instruction performs unary operations. In the next few sections, we will discuss how each of these instructions can be used to perform logical operations when used in an assembly program.

Programing with binary operations in x86 assembly

A binary operation is performed on two operands to return a result. AND, OR and XOR are examples of instructions that perform binary operations. The following assembly program written in x86 assembly provides an overview of these binary operations and we will also discuss how they can also have an effect on the program’s control flow.

section .text

global _start

_start:

;logical and

mov eax, 20

mov ebx, 0

and eax, ebx

jnz _exit

;logical or

mov eax, 20

or eax, ebx

jz _exit

;logical xor

xor eax, eax

;gracefully exit the program

_exit:

mov eax, 1

mov ebx, 0

int 0x80

The instructions within the .text section will get executed from the entry point, which is  _start.  The program has 4 sections within it. The first section performs logical and, the second section performs logical or, the third section performs logical exclusive or and the last section of the code gracefully exits the program.

We are initializing the registers eax and ebx using the following instructions.

  • mov eax, 20
  • mov ebx, 0

The next instruction and eax, ebx performs a binary operation, which is a bitwise and operation. The result of this operation will be zero and the output will be placed in the first operand, which is eax in this case. This instruction will also have effects on the condition flags as follows.

  • SF becomes the value of the most significant bit of the calculated result.
  • ZF will be set if the result is 0.
  • PF is set according to the result

In our case, the result is zero and thus the ZF will be set. We can use this effect to control the flow of the program by making use of instructions such JE, JNE, JZ, JNZ. In the preceding program, the program will execute the _exit routine if the ZF is not set. In this case, the ZF will be set and thus the instruction jnz _exit will not take the jump.

Next, in preparation to demonstrate the OR instruction, we are once again initializing the EAX register with the value 20 using the following instruction.

  • mov eax, 20

Once this instruction is executed eax contains the value 20 and ebx register contains the value 0.  The OR instruction performs an exclusive or operation on the two operands and the result will be stored in the first operand. The or eax, ebx instruction in this case will store the value 20 in eax after the exclusive or operation. Once again the jump will not be taken when executing the jz _exit instruction as the ZF flag is not set by the previous instruction.

Finally, the logical exclusive or (xor) operation is performed when xor instruction is executed. One use case of xor instruction is to zero out a register. So, when xor eax, eax instruction is executed, the eax register will contain the value 0.

Programming with unary operations in x86 assembly

In contrast to binary operations where two operands are used, a unary operation is an operation with only one operand. NOT is an example of an instruction that performs unary operation. The following assembly program written in x86 assembly provides an overview of unary operation. This will not have any effect on the conditional flags.

section .text

global _start

_start:

;logical not

mov eax, 20

not eax

_exit:

mov eax, 1

mov ebx, 0

int 0x80

The instructions within the .text section will get executed from the entry point, which is  _start.  We are initializing the register eax using the following instruction.

  • mov eax, 20

The next instruction not eax performs a bitwise inversion of the value stored in the eax register. GDB shows the following in the eax register, before the not instruction is executed.

$eax   : 0x14

After executing the not instruction, GDB shows the following in the eax register.

$eax   : 0xffffffeb

Let us observe how this value is derived after performing a not operation on the decimal value 20. Following is the 32 bit binary equivalent of decimal 20.

00000000000000000000000000010100

A bitwise not on the preceding value results in the following.

11111111111111111111111111101011

Following is the hex equivalent of the preceding value.

0xFFFFFFEB

This is the value shown by GDB after the NOT instruction is executed.

Conclusion

This article has provided an overview of logic instructions AND, OR, XOR and NOT. The instructions AND, OR and XOR perform binary operations with two operands while the NOT instruction performs unary operations with just one operand. When AND, OR and XOR instructions have an effect on the conditional flags, which can be used to control the flow of the program, while the NOT instruction does not have any effect on these flags.

 

Sources

Posted: February 17, 2021
Articles Author
Srinivas
View Profile

Srinivas is an Information Security professional with 4 years of industry experience in Web, Mobile and Infrastructure Penetration Testing. He is currently a security researcher at Infosec Institute Inc. He holds Offensive Security Certified Professional(OSCP) Certification. He blogs atwww.androidpentesting.com. Email: srini0x00@gmail.com