/*personal notes of renzo diomedi*/

~ 00000100 ~





UNCONDITIONAL BRANCHES
When an unconditional branch is encountered in the program, the instruction pointer is automatically routed to a different locations:
❑ Jumps
❑ Calls
❑ Interrupt
.....❑ Software interrupts
.....❑ Hardware interrupts
...../*interrupt controller chip receives the signal */
...../*and gives the interrupt number to microprocessor*/
...../*also used to return to os , 0x21 windows , 0x80 linux*/
...../*in most cases the microprocessor push the address */
...../*of the current interrupted execution in the stack */
...../*then the bios exe the instructions then generate */
...../*an IRet interrupt return that allows to microprocessor */
...../*to retrieve the address in the stack and resume */
...../*the interrupted execution */



CONDITIONAL BRANCHES
Unlike unconditional branches, conditional branches are not always taken. The result of the conditional branch depends on the state of the EFLAGS register at the time the branch is executed. There are many bits in the EFLAGS register, but the conditional branches are only concerned with five of them:
❑ Carry flag (CF) - bit 0 (lease significant bit)
❑ Overflow flag (OF) - bit 11
❑ Parity flag (PF) - bit 2
❑ Sign flag (SF) - bit 7
❑ Zero flag (ZF) - bit 6
Each conditional jump instruction examines specific flag bits to determine whether the condition is proper for the jump to occur. With five different flag bits, several jump combinations can be performed. The following sections describe the individual jump instructions.
Conditional jump instructions
The conditional jumps determine whether or not to jump based on the current value of the EFLAGS register. Several different conditional jump instructions use different bits of the EFLAGS register. The format of the conditional jump instruction is
jxx address
where xx is a one- to three-character code for the condition, and address is the location within the program to jump to (usually denoted by a label).



JA Jump if above CF=0 and ZF=0
JAE Jump if above or equal CF=0
JB Jump if below CF=1
JBE Jump if below or equal CF=1 or ZF=1
JC Jump if carry CF=1
JCXZ Jump if CX register is 0
JECXZ Jump if ECX register is 0
JE Jump if equal ZF=1
JG Jump if greater ZF=0 and SF=OF
JGE Jump if greater or equal SF=OF
JL Jump if less SF<>OF
JLE Jump if less or equal ZF=1 or SF<>OF
JNA Jump if not above CF=1 or ZF=1
JNAE Jump if not above or equal CF=1
JNB Jump if not below CF=0
JNBE Jump if not below or equal CF=0 and ZF=0
JNC Jump if not carry CF=0
JNE Jump if not equal ZF=0
JNG Jump if not greater ZF=1 or SF<>OF
JNGE Jump if not greater or equal SF<>OF
JNL Jump if not less SF=OF
JNLE Jump if not less or equal ZF=0 and SF=OF
JNO Jump if not overflow OF=0
JNP Jump if not parity PF=0
JNS Jump if not sign SF=0
JNZ Jump if not zero ZF=0
JO Jump if overflow OF=1
JP Jump if parity PF=1
JPE Jump if parity even PF=1
JPO Jump if parity odd PF=0
JS Jump if sign SF=1
JZ Jump if zero ZF=1



// jt
.section .text
.globl _start
_start:
nop
movl $1, %eax
jmp overhier
movl $10, %ebx
int $0x80
overhier:
movl $20, %ebx
int $0x80


C:\>objdump -d users\rnz\desktop\jt.exe
users\rnz\desktop\jt.exe: file format pei-i386
Disassembly of section .text:

00401000 <_start>:
401000: 90 nop
401001: b8 01 00 00 00 mov $0x1,%eax
401006: eb 07 jmp 40100f
401008: bb 0a 00 00 00 mov $0xa,%ebx
40100d: cd 80 int $0x80

0040100f :
40100f: bb 14 00 00 00 mov $0x14,%ebx
401014: cd 80 int $0x80
401016: 90 nop
401017: 90 nop

00401018 <__CTOR_LIST__>:
401018: ff (bad)
401019: ff (bad)
40101a: ff (bad)
40101b: ff 00 incl (%eax)
40101d: 00 00 add %al,(%eax)

00401020 <__DTOR_LIST__>:
401020: ff (bad)
401021: ff (bad)
401022: ff (bad)
401023: ff 00 incl (%eax)
401025: 00 00 add %al,(%eax)



renzo@renzo-AO531h:~/Scrivania$ as -gstabs -o jt.o jt.s
renzo@renzo-AO531h:~/Scrivania$ ld -o jt jt.o

renzo@renzo-AO531h:~/Scrivania$ objdump -d jt
jt: formato del file elf32-i386
Disassemblamento della sezione .text:

08048054 <_start>:
8048054: 90 nop
8048055: b8 01 00 00 00 mov $0x1,%eax
804805a: eb 07 jmp 8048063
804805c: bb 0a 00 00 00 mov $0xa,%ebx
8048061: cd 80 int $0x80

08048063 :
8048063: bb 14 00 00 00 mov $0x14,%ebx
8048068: cd 80 int $0x80

renzo@renzo-AO531h:~/Scrivania$ gdb -q jt
Reading symbols from jt...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048055: file jt.s, line 6.
(gdb) run
Starting program: /home/renzo/Scrivania/jt
Breakpoint 1, _start () at jt.s:6
6 movl $1, %eax
(gdb) print/x $eip
$1 = 0x8048055
(gdb) step
7 jmp overhier
(gdb) step
11 movl $20, %ebx
(gdb) print/x $eip
$2 = 0x8048063
(gdb)






LABEL CALLED :
pushl %ebp
movl %esp, %ebp
//normal function here
movl %ebp, %esp
popl %ebp
ret




# call_x
.section .data
output:
.asciz "This is section n. %d\n"
.section .text
.globl _start
_start:
pushl $1
pushl $output
call printf
add $8, %esp # should clear up stack
call overhere
pushl $3
pushl $output
call printf
add $8, %esp # should clear up stack
pushl $0
call exit
overhere:
pushl %ebp
movl %esp, %ebp
pushl $2
pushl $output
call printf
add $8, %esp # should clear up stack
movl %ebp, %esp
popl %ebp
ret

$ ./call_x
This is section n. 1
This is section n. 2
This is section n. 3
$






cmp operand1, operand2 #(operand2 – operand1)


❑ Overflow flag (OF) - It is set when a signed value is too large for the data element containing it. This usually happens during arithmetic operations that overflow the size of the register holding the data.

❑ Parity flag (PF) - If the number of bits set to one in the resultant is even, the parity bit is set (one). If the number of bits set to one in the resultant is odd, the parity bit is not set (zero).

❑ Sign flag (SF) - The sign flag is used in signed numbers to indicate a sign change in the value contained in the register. In a signed number, the last bit is used as the sign bit. It indicates whether the numeric representation is negative (set to 1) or positive (set to 0).

❑ Zero flag (ZF) - if it's set (the two operands are equal) , JE , JZ branch

❑ Carry flag (CF) - The carry flag is used in mathematical expressions to indicate when an overflow has occurred in an unsigned number (remember that signed numbers use the overflow flag). The carry flag is set when an instruction causes a register to go beyond its data size limit.
Unlike the overflow flag, the DEC and INC instructions do not affect the carry flag.
The carry flag will also be set when an unsigned value is less than zero. For example, this code snippet will also set the carry flag:
movl $2, %eax
subl $4, %eax
jc overflow
The resulting value in the EAX register is 254, which represents –2 as a signed number, the correct answer. This means that the overflow flag would not be set. However, because the answer is below zero for an unsigned number, the carry flag is set.
Unlike the other flags, there are instructions that can specifically modify the carry flag. These are described in the following table.
....................CLC Clear the carry flag (set it to zero)
....................CMC Complement the carry flag (change it to the opposite of what is set)
....................STC Set the carry flag (set it to one)valuebit 0 (lease significant bit)





jxx address (label)
The conditional jump instructions take a single operand in the instruction code—the address to jump to. While usually a label in an assembly language program, the operand is converted into an offset address in the instruction code. Two types of jumps are allowed for conditional jumps:
❑ Short jumps
❑ Near jumps
A short jump uses an 8-bit signed address offset, whereas a near jump uses either a 16-bit or 32-bit signed address offset. The offset value is added to the instruction pointer.
Conditional jump instructions do not support far jumps in the segmented memory model. If you are programming in the segmented memory model, you must use programming logic to determine whether the condition




The loop instructions use the ECX register as a counter and automatically decrease its value as the loop instruction is executed.

Instruction .............. Description

LOOP ..................... Loop until the ECX register is zero
LOOPE/LOOPZ .............. Loop until either the ECX register is zero, or the ZF flag is not set
LOOPNE/LOOPNZ ............ Loop until either the ECX register is zero, or the ZF flag is set

The LOOPE/LOOPZ and LOOPNE/LOOPNZ instructions provide the additional benefit of monitoring the Zero flag.

The format for each of these instructions is

loop address

where address is a label name for a location in the program code to jump to.
Unfortunately, the loop instructions support only an 8-bit offset, so only short jumps can be performed.
Before the loop starts, you must set the value for the number of iterations to perform in the ECX register.
This usually looks something like the following:

< code before the loop >
movl $100, %ecx
loop1:
< code to loop through >
loop loop1
< code after the loop >

Be careful with the code inside the loop. If the ECX register is modified, it will affect the operation of the loop. Use extra caution when implementing function calls within the loop, as functions can easily trash the value of the ECX register without you knowing it.
An added benefit of the loop instructions is that they decrease the value of the ECX register without affecting the EFLAGS register flag bits. When the ECX register reaches zero, the Zero flag is not set.


# luup
.section .data
output:
.asciz " The value is: %d\n "
.section .text
.globl _start
_start:
movl $100, %ecx
movl $0, %eax
luup:
addl %ecx, %eax
loop luup
pushl %eax
pushl $output
call printf
add $8, %esp
movl $1, %eax
movl $0, %ebx
int $0x80


if the value of ECX is already zero before the LOOP instruction, it will be decreased by one, making it -1.
Because this value is not zero, the LOOP instruction continues on its way, looping back to the defined label. The loop will eventually exit when the register overflows, and the incorrect value is displayed.


JCXZ instruction is used to perform a conditional branch if the ECX register is zero. This is exactly what we need to solve this problem.







DISASSEMBLING a C program


/* ifthen.c */
#include
int main()
{
int a = 100;
int b = 25;
if (a > b)
{
printf("The higher value is %d\n", a);
} else
printf("The higher value is %d\n", b);
return 0;
}


renzo@renzo-AO531h:~/Scrivania$ gcc -S ifthen.c
renzo@renzo-AO531h:~/Scrivania$ cat ifthen.s
.file "ifthen.c"
.text
.section .rodata
.LC0:
.string "The higher value is %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
leal 4(%esp), %ecx
.cfi_def_cfa 1, 0
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
.cfi_escape 0x10,0x5,0x2,0x75,0
movl %esp, %ebp
pushl %ebx
pushl %ecx
.cfi_escape 0xf,0x3,0x75,0x78,0x6
.cfi_escape 0x10,0x3,0x2,0x75,0x7c
subl $16, %esp
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
movl $100, -16(%ebp)
movl $25, -12(%ebp)
movl -16(%ebp), %edx
cmpl -12(%ebp), %edx
jle .L2
subl $8, %esp
pushl -16(%ebp)
leal .LC0@GOTOFF(%eax), %edx
pushl %edx
movl %eax, %ebx
call printf@PLT
addl $16, %esp
jmp .L3
.L2:
subl $8, %esp
pushl -12(%ebp)
leal .LC0@GOTOFF(%eax), %edx
pushl %edx
movl %eax, %ebx
call printf@PLT
addl $16, %esp
.L3:
movl $0, %eax
leal -8(%ebp), %esp
popl %ecx
.cfi_restore 1
.cfi_def_cfa 1, 0
popl %ebx
.cfi_restore 3
popl %ebp
.cfi_restore 5
leal -4(%ecx), %esp
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
.globl __x86.get_pc_thunk.ax
.hidden __x86.get_pc_thunk.ax
.type __x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
.LFB1:
.cfi_startproc
movl (%esp), %eax
ret
.cfi_endproc
.LFE1:
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits





CODE ANALYSIS :


pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp

//stores the EBP register so it can be used as a pointer to the local stack area in the program. The stack pointer, ESP, is then manually manipulated to make room for putting local variables on the stack.


movl $100, -4(%ebp)
movl $25, -8(%ebp)

// creates the two variables used in the If statement. the first instruction manually moves the value for the a variable into a location on the stack (4 bytes in front of the location pointed to by the EBP register). The second instruction manually moves the value for the b variable into the next location on the stack (8 bytes in front of the location pointed to by the EBP register). This technique, is commonly used in functions. Now that both variables are stored on the stack, it’s time to execute the if statement:


movl -4(%ebp), %eax
cmpl -8(%ebp), %eax
jle .L2

// First, the value for the a variable is moved to the EAX register, and then that value is compared to the value for the b variable, still in the local stack. Instead of looking for the if condition a > b, the assembly language code is looking for the opposite, a <= b. If the statement evaluates to “true,” the jump to the .L2 label is made, which is the “else” part of the If statement:


.L2:
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf

// This is the code to print the answer for the b variable, which was contained in the else part of the If statement. First the b variable value is retrieved and manually placed on the stack, and then the location of the output text (located at the .LC0 label) is placed on the stack. With both elements on the stack, the printf C function is called to display the answer. The code then proceeds to the ending instructions.


// If the JLE instruction was false, then a is not less than or equal to b, and the jump is not performed. Instead, the “then” part of the If statement is performed:

movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
jmp .L3

// Here, the a variable is loaded onto the stack, along with the output text. Then the printf C function is called to display the answer, and execution jumps to the .L3 label.


Finally, all roads load to the exit C function

.L3:
movl $0, (%esp)
call exit
.size main, .-main
.section .note.GNU-stack,””,@progbits
.ident "GCC: linux distro








HOME PAGE