随笔-汇编笔记(ing...)


https://www.godbolt.org/

gcc内嵌汇编

byeyear: 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调试,发现并不是

网上查找"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对它们进行重新排序。这样就可以控制局部变量在栈上的排列顺序。

函数调用过程和参数传递

测试代码:

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 发生变化

注: 图上注释对了吗?

A: 错了,push 应该是esp - 4,又巩固了一下,栈是往低地址延伸(一般我们会画图,高地址在上面,低地址在下,形象的称栈是向下,堆是向上)

posted @ 2023-11-19 17:18  LiYanbin  阅读(1)  评论(0编辑  收藏  举报