测试代码#include <stdio.h>
int test_if(int x) {
if (x > 10) {
return 1;
} else {
return 0;
int test_for(int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += i;
return sum;
int test_while(int x) {
while (x > 0) {
x--;
return x;
int test_switch(int x) {
switch (x) {
case 0: return 100;
case 1: return 200;
case 2: return 300;
default: return -1;
int main() {
printf("%d\n", test_if(15));
printf("%d\n", test_for(10));
printf("%d\n", test_while(5));
printf("%d\n", test_switch(1));
return 0;
}运行环境:
Ubuntu 20.04.6 LTS编译指令:
gcc -g -O0 -o main main.cgcc版本 gcc version 9.4.0调试工具: GDB
gdb ./main启动调试:进入main函数内部 (gdb) x/10i $rip 0x5555555551f7 <main>: endbr64 0x5555555551fb <main+4>: push %rbp 0x5555555551fc <main+5>: mov %rsp,%rbp 0x5555555551ff <main+8>: mov $0xf,%edi 0x555555555204 <main+13>: callq 0x555555555149 <test_if>
发现在调用test_if时,传递了一个参数,参数为0xf
单步调试进入test_if函数:
0x555555555149 <test_if>: endbr64 0x55555555514d <test_if+4>: push %rbp 0x55555555514e <test_if+5>: mov %rsp,%rbp 0x555555555151 <test_if+8>: mov %edi,-0x4(%rbp) 0x555555555154 <test_if+11>: cmpl $0xa,-0x4(%rbp) 0x555555555158 <test_if+15>: jle 0x555555555161 <test_if+24> 0x55555555515a <test_if+17>: mov $0x1,%eax 0x55555555515f <test_if+22>: jmp 0x555555555166 <test_if+29> 0x555555555161 <test_if+24>: mov $0x0,%eax 0x555555555166 <test_if+29>: pop %rbp 0x555555555167 <test_if+30>: retq
发现cmpl 指令,对比了 0xa,与参数0xf jle 指令,判断0xf 是否小于等于 0xa 通过jle指令可以看出是有符号比较 0xa = 10, 0xf = 15 如果小于等于则跳转0x555555555161,将0赋值给eax,后返回函数,则函数返回值为0 如果大于0xa则继续向下执行 将eax赋值为1跳转到0x555555555166,函数返回。 即: if (a <= b){ retrun 0; }else{ return 1; } 该函数返回值为1
0x555555555209 <main+18>: mov %eax,%esi 0x55555555520b <main+20>: lea 0xdf2(%rip),%rdi # 0x555555556004 0x555555555212 <main+27>: mov $0x0,%eax 0x555555555217 <main+32>: callq 0x555555555050 <printf@plt> 0x55555555521c <main+37>: mov $0xa,%edi
执行printf函数输出1
继续执行 0x55555555521c <main+37>: mov $0xa,%edi 0x555555555221 <main+42>: callq 0x555555555168 <test_for> 传递了一个参数0xa 进入test_for: 0x555555555168 <test_for>: endbr64 0x55555555516c <test_for+4>: push %rbp 0x55555555516d <test_for+5>: mov %rsp,%rbp 0x555555555170 <test_for+8>: mov %edi,-0x14(%rbp) 0x555555555173 <test_for+11>: movl $0x0,-0x8(%rbp) 0x55555555517a <test_for+18>: movl $0x0,-0x4(%rbp) 0x555555555181 <test_for+25>: jmp 0x55555555518d <test_for+37> 0x555555555183 <test_for+27>: mov -0x4(%rbp),%eax 0x555555555186 <test_for+30>: add %eax,-0x8(%rbp) 0x555555555189 <test_for+33>: addl $0x1,-0x4(%rbp) 0x55555555518d <test_for+37>: mov -0x4(%rbp),%eax 0x555555555
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-291286.htm
[原创]从GDB中观察x86-64函数控制流
91 浏览
0 回复
暂无回复,快来抢沙发吧!