"Copyright Notice: respect for the original, reproduced please retain the source: blog.csdn.net/shallnet, the article only for learning Exchange, do not use for commercial purposes"
The assembly code examples we used before are all starting from the first instruction until the last instruction program exits. But in fact, like high-level languages, assembler code also provides instructions to change the way the program processes data. Under normal circumstances, the next instruction that the program executes to execute is in the instruction pointer register, which determines which instruction in the program is the next instruction to be executed. the EIP register increments when the instruction pointer moves through the program instructions. The instruction length may be multiple bytes, so pointing to the next instruction is more than just a single increment of the instruction pointer each time. the instruction Pointer Register (EIP) tracks the next instruction code to execute the program, the application cannot modify the instruction pointer itself, cannot be placed in the EIP with the specified memory address, instead it must use instructions that change the instruction pointer to change the next instruction of the pre-access cache, which is called the branch instruction. The branch instruction can change the value of the EIP register, either unconditionally or by conditional change. when a program encounters a jump, call, or interrupt, the instruction pointer automatically jumps to another location.
The jump instruction uses a single instruction code:jmp Locationwhere location is the memory address to jump to. In assembly language, this position is a label in the program code, similar to the goto statement in C. When this instruction is encountered, the instruction pointer changes to the memory address of the script following the label. The following example shows a jump instruction operation:
# jmp.s.section Text.globl _start_start: NOP movl $,%eax jmp gotohere movl $,%ebx int $ 0x80gotohere: movl $,%ebx int $0x80
compile execution to see the results returned by the program:
$ makeas-o jmp.o jmp.s--gstabsld-o jmp jmp.o$./jmp$ Echo $?20
The program simply calls the system call exit, and by looking at the program execution return code you can determine that the jump occurred. We can also step through the debugger to see each line of code running to determine the jump to occur. as follows:
(GDB) b *_startbreakpoint 1 at 0x8048054:file Jmp.s, line 5. (GDB) rstarting program:/home/allen/as/4_jmp/jmpbreakpoint 1, _start () at jmp.s:55 NOP (gdb) S6 MOVL $,%eax (GD b) S7 jmp gotohere (gdb) S11 movl $,%ebx (GDB) s12 int $0x80 (GDB) Sprogram exited with code 024. ( GdB
Recompile the program, remove debugging information, and use the Objdump program to disassemble the executable program to see how the script is arranged in memory:
$ as-o jmp.o jmp.s $ ld-o jmp JMP.O $ objdump-d jmpjmp: file format elf32-i386disassembly of section. text:08048054 <_start>: 8048054:90 nop 8048055:b8, xx $0x1,%eax 804805a:eb, jmp 8048063 < gotohere> 804805c:bb 0a xx $0XA,%EBX mov 8048061:cd int $0x8008048063 <gotohere> ;: 804 8063:BB xx $0x14,%ebx 8048068:cd int $0x80
The value of the EIP register can now be viewed in the debugger against the script memory location in the disassembler in the debug program using the program make compiler.
Breakpoint 1, _start () at jmp.s:55 NOP (gdb) N6 movl $,%eax (gdb) N7 jmp gotohere (gdb) print $eip $ = (void ( *) ()) 0x804805a <_start+6> (gdb) N11 movl $,%ebx (GDB) print $eip $ = (void (*) ()) 0x8048063 <gotohere> (g db
as you can see, the output EIP address 0x8048063 is the memory location that the Gotohere tag points to.
The calling instruction is similar to a jump instruction, but it saves the location where the jump occurred, and can return to that location if necessary. In assembly language, the implementation function uses the calling instruction. Similar to C language, assembly language functions are also segmented function modules, avoid writing the same code many times. Invoke instruction Usage:Call addraddr refers to the tag in the program for the operand, which is converted to the memory address of the first instruction in the function. The function returns the original part of the code using the mnemonic ret. When the call instruction is executed, the instruction puts the value of the EIP register on the stack and modifies the EIP register to point to the called function address. When the called function completes, it obtains the past EIP register value from the stack, and returns control to the original program, since it is possible to manipulate the stack in the function, so EBP is often used as the base pointer for the stack, so the ESP register is also often copied to the EBP register at the beginning of the function. We can therefore give a template of an assembly language function:
Func_lable: push1%ebp movl%esp,%ebp <function code here> movl%ebp,%esp popl%ebp Ret
after you save the EBP register, you can use it as the base pointer to the stack, making all access to the stack in the function. Before the function returns, the ESP register must be reverted to point to the memory location where the call was made. The following shows a simple call example:
#call. s.section. Datamsg: . Asciz "This was as call test!\n" len=.-msg.section. Text.globl _start_start: NOP Call Output_func movl $,%ebx movl $,%eax int $0x80output_func: pushl%ebp movl%esp,%ebp< C9/>#<function code here> movl $len,%edx movl $msg,%ecx movl $,%ebx movl $4,%eax int $0x80 movl%ebp,%esp popl%ebp ret
The program calls the function Output_func output a string of strings. Make and execute the results as follows:
interrupts can also change the current instruction pointer. Interrupts the soft interrupt and the hard interrupt, when a program is interrupted, the pointer pointer is transferred to the called program, and continues from within the called program, the called program completes, it can return control to the calling program. In the examples given in the previous sections, interrupts have been used. The simple int instruction that uses the 0X80 value transfers control to the Linux system Invoker, which executes the sub-function at the value of the EAX register at the time of the interrupt, and the details of the interrupt are described later.
Conditional Jumpconditional jumps Follow the values in EFlags to determine whether to jump. Each conditional jump instruction checks for a specific flag bit to determine whether a jump condition is met. There are many bits in the EFlags register, and there are 5 bits related to conditional jumps: 0 bits (carry flag CF), 11 bits (overflow flag of), 2 bits (parity flag PF), 7 bits (sign sign SF), 6th bit (0 sign ZF). Combining these several different flags can perform a variety of jump combinations. The conditional jump instruction format is as follows:jxx Addrwhere xx is a conditional code of 1 to 3 characters, addr is the location where the program jumps to. The following are all the available conditional jump directives. a greater than when jumpAE is greater than or equalB is less thanBe is less than or equalC RoundingCXZ If the CX register is 0ECXZ If the ECS register is 0e equalna is less thannae not greater than or equal toNB not less thanNbe not less than or equal toNC Non-roundingne is not equal toG is greater than (signed)GE is greater than or equal to (signed)L less than (signed)Le is less than or equal (signed)ng not greater than (signed)Nge not greater than or equal (signed)nl not less thanNle not less than or equal toNo no overflowNP-no parity checkNS unsignedNZ non 0o overflowp parity CheckPE if even checkpo if odd checkS if signedZ If it is zero
The EFlags register can be set by comparing two values with a comparison instruction, and the comparison instruction CMP format is as follows:cmp operand1, Operand2The instruction compares the second operand to the first operand, performs a subtraction operation on the two operands (OPERAND2-OPERAND1), and then sets the Efalgs register. The following example:
#cmp. S.section. Text.globl _start_start: nop movl $11,%eax movl $24,%EBX cmp%eax,%ebx Jae Greater MOVL $ $,%eax int $0x80greater: movl $11,%EBX movl $,%eax int $0x80
Make , the results of the operation are as follows:
$ makeas-o CMP.O CMP.S--gstabsld-o cmp cmp.o$./cmp $ echo $?11
by looking at the program return output the result indicates that a conditional jump has occurred, the value of the EBX register is greater than the value in the size register, so the code jumps to the greater label, or you can step through the debugger to see the code execution order.
Linux Platform x86 compilation (eight): Conditional jump