正常情况下,指令是按照顺序执行的,跳转指令会导致程序的执行切换到一个新位置。
jmp跳转指令是无条件跳转指令。
可以是直接跳转,即跳转指令的目的地址通常由标号指明。也可以是间接跳转:
jmp *%eax //用eax值作为跳转目的地址。
jmp *(%eax) //用eax指向的内存中保存的地址值作为跳转目的地址。
有条件跳转指令如下:
je Label //相等跳转
jz Label //与je相同
jne Label //不相等跳转
jnz Label //与jne相同
js Label //负数跳转
jns Label //非负数跳转
jg Label //有符号大于跳转
jnle Label //与jg相同
jge Label //有符号大于等于跳转
jnl //与jge相同
jl Label //有符号小于跳转
jnge Label //与jl相同
jle Label //有符号小于等于跳转
jng Label //与jle相同
ja Label //无符号大于跳转
jnbe Label //与ja相同
jae Label //无符号大于等于跳转
jnb //与jae相同
jb Label //无符号小于跳转
jnae Label //与jb相同
jbe Label //无符号小于等于跳转
jna Label //与jbe相同
示例:
int absdiff(int x, int y)
{
if (x < y)
returny - x;
else
returnx - y;
}
gcc -O1 -S -m32 abs_diff1.c
absdiff:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx //edx = x
movl 12(%ebp), %eax //eax = y
cmpl %eax, %edx //比较x和y
jge .L2 //x >=y,跳转到L2
subl %edx, %eax //eax = y -x
jmp .L4 //跳转到L4
.L2:
subl %eax, %edx //edx = x -y
movl %edx, %eax //eax = edx =x-y
.L4:
popl %ebp
ret
gcc -O1 -m32 -c abs_diff1.c
objdump -d abs_diff1.o
abs_diff1.o: file format elf32-i386
Disassembly of section .text:
00000000 <absdiff>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 55 08 mov 0x8(%ebp),%edx
6: 8b 45 0c mov 0xc(%ebp),%eax
9: 39 c2 cmp %eax,%edx
b: 7d 04 jge 11 <absdiff+0x11>
d: 29 d0 sub %edx,%eax
f: eb 04 jmp 15 <absdiff+0x15>
11: 29 c2 sub %eax,%edx
13: 89 d0 mov %edx,%eax
15: 5d pop %ebp
16: c3 ret
内容基本相同,只是跳转的标号变成了相对地址:
b: 7d 04,04就是相对地址偏移,表示跳转到本条指令的下一条指令的地址加上这个偏移(0xd+0x4=0x11)。
f: eb 04,同理,表示跳转到(0x11+0x4=0x15)。
int gotodiff(int x, int y)
{
int rval;
if (x < y)
gotoless;
rval = x - y;
goto done;
less:
rval = y - x;
done:
return rval;
}
gcc -O1 -S -m32 abs_diff_goto.c
gotodiff:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx//edx = x
movl 12(%ebp), %eax //eax = y
cmpl %eax, %edx //比较x和y
jl .L2 //x<y跳转到L2
subl %eax, %edx //edx = x - y
movl %edx, %eax //eax = edx =x-y
jmp .L4 //跳转到L4
.L2:
subl %edx, %eax //eax = y - x
.L4:
popl %ebp
ret