随笔-汇编笔记(ing...)
gcc内嵌汇编
查看汇编代码
disassemble a single function using objdump
objdump -d -M intel name_of_your_obj_file | awk -F"\n" -v RS="\n\n" '$1 ~ /main/'
栈变量分配规则[gcc compiler]
一直以为栈空间变量的排布是按照顺序
int xxxfunc(...)
{
struct xxx *xobj = null;
...
int err, argc = 0, id;
char *argv[12] = {0x0};
...
argc = separate_string(...); // 一直都是6
...
xobj = hash_find(hash_list, &id, sizeof(&id));
...
// 移除
if (...)
switch_hash_insert(hash_list, &id, sizeof(&id), NULL);
// 插入
else
switch_hash_insert(hash_list, &id, sizeof(&id), xobj);
...
}
显然,错误比较明显,这是个64位程序,int id 是4字节,但是访问了8字节
+++
但是细想,argc不管是插入还是移除场景都是6,那么id还是一样的(int id 4字节 + argc 4字节),也就能正常插入和移除,但是现场报了前端移除了但是实际没移除
按照一般理解,&id, sizeof(&id) 也就是 argc 和 id 的内存地址的值,后面通过gdb调试,发现并不是
![](https://img2024.cnblogs.com/blog/2679005/202401/2679005-20240118202958635-1854744375.png)
网上查找"gcc编译器栈变量规则" or "gcc complilers how to arrange local variable on the stack",没有找到具体出处, 不过可以理解为因为一些对其或者访问频率自动排布。
chatgpt的回答:
在C语言中,局部变量的存储顺序是由编译器决定的,通常是根据优化级别和变量类型进行排列。对于GCC编译器,你可以通过使用结构体来控制局部变量在栈上的顺序。下面是一个示例代码:
void function1() {
struct {
int x;
int y;
int z;
int *ret;
} locals;
}
通过将局部变量放入结构体中,可以防止GCC对它们进行重新排序。这样就可以控制局部变量在栈上的排列顺序。
函数调用过程和参数传递
![](https://img2023.cnblogs.com/blog/2679005/202311/2679005-20231119170733622-650715600.png)
测试代码:
unfold
typedef int (*FUNCPTR) ();
/* Type your code here, or load an example. */
int square1(int num) {
return num + num;
}
int square2(int num1, int num2) {
return num1 + num2;
}
int run_cb(FUNCPTR fn, int num1, int num2)
{
return fn(num1, num2);
}
int main(int argc, void *argv[])
{
int a = 1, b = 2;
run_cb((FUNCPTR)square1, a, b);
run_cb((FUNCPTR)square2, a, b);
}
汇编代码:
call 和 push 都会导致 esp 发生变化
![](https://img2023.cnblogs.com/blog/2679005/202311/2679005-20231119170905592-1534831573.png)
注: 图上注释对了吗?
A: 错了,push 应该是esp - 4
,又巩固了一下,栈是往低地址延伸(一般我们会画图,高地址在上面,低地址在下,形象的称栈是向下,堆是向上)
![](https://img2023.cnblogs.com/blog/2679005/202311/2679005-20231119171300245-2060189252.png)
本文来自博客园,作者:LiYanbin,转载请注明原文链接:https://www.cnblogs.com/stellar-liyanbin/p/17842294.html