C与汇编的混合编程问题,有懂汇编的大神么?

Fuz 发布于 2012/06/01 00:45
阅读 660
收藏 0
最近在学习c与汇编的混合编程,遇到了一个问题。简单说来,就是我希望用汇编在内存里预留一块内存,然后把这块内存的地址作为C中的一个结构体指针,用对结构体的成员赋值的方式来直接改变内存单元的值。代码如下:

/*文件 asm.c */
//首先定义了一个简单结构体,只有两个int成员
struct tmp{
    int a;
    int b;
};
extern struct tmp *t; //将 src.s 文件中预留的内存块导入,并强制转换为struct tmp类型的指针
int main()
{
    t->a=1;     //用对结构体成员赋值的方式直接操作相关内存单元
    t->b=2;
    return 0;
}

/*超简单的汇编文件 src.s ,用的是AT&T 风格的代码*/
.global t               //导出变量 t
t:
    .word 0,0         //占用两个双字的内存空间并填0,
    .word 0,0          //即整好两个int变量的长度 4×2

编译并链接
 gcc asm.c -c
 gcc src.s -c
 gcc src.o asm.o
生成了可执行的 a.out文件。到现在为止还没有任何问题,但是当执行a.out文件时,会直接报段错误。想来如此简单的代码,逻辑上出错的可能性微乎其微,内存操作上也似乎并无太大不妥啊,为什么会错呢?求大神指点迷津啊~~

加载中
0
周翼翼
周翼翼

extern struct tmp *t 是一个指针变量,它也要4字节.

而且,你要把

.global t               //导出变量 t
t:
    .word 0,0         //占用两个双字的内存空间并填0,
    .word 0,0 

这块内存的地址给它.

代码:

/*文件test.c */
#include <stdio.h>
struct tmp{
    int a;
    int b;
};
extern struct tmp *t;
int main()
{
    init();
    t->a = 3211;    
    t->b = 1123;
    printf("%d %d\n",t->a, t->b);
    return 0;
} 

//asm.s
.comm _t, 4
.comm _st, 8

.text
.globl	_init
_init:
    movl $_st, _t
    ret

//makefile
test.exe:
	gcc -o test.exe test.c asm.s

Fuz
Fuz
好吧,我表示浏览器没有加载完全,没看到后面的代码,不好意思哈
0
Fuz
Fuz

引用来自“周翼翼”的答案

extern struct tmp *t 是一个指针变量,它也要4字节.

而且,你要把

.global t               //导出变量 t
t:
    .word 0,0         //占用两个双字的内存空间并填0,
    .word 0,0 

这块内存的地址给它.

代码:

/*文件test.c */
#include <stdio.h>
struct tmp{
    int a;
    int b;
};
extern struct tmp *t;
int main()
{
    init();
    t->a = 3211;    
    t->b = 1123;
    printf("%d %d\n",t->a, t->b);
    return 0;
} 

//asm.s
.comm _t, 4
.comm _st, 8

.text
.globl	_init
_init:
    movl $_st, _t
    ret

//makefile
test.exe:
	gcc -o test.exe test.c asm.s

我把代码改成了下面这样,但还是错。用gdb调试发现 t 和 tptr 的值都是不可预期的,为什么会这样?你能告诉我怎么做不?
/*file src.s*/
.global t
.global tptr
t:
    .word 0
    .word 0
    .word 0
    .word 0

tptr:
    .word 0
    .word 0

/*file asm.c*/
struct tmp{
    int a;
    int b;
};

extern struct tmp *t;
extern long tptr;

int main()
{
    t=tptr;
    t->a=1;
    t->b=2;
    return 0;
}
0
周翼翼
周翼翼

引用来自“子逸是也!”的答案

引用来自“周翼翼”的答案

...

我把代码改成了下面这样,但还是错。用gdb调试发现 t 和 tptr 的值都是不可预期的,为什么会这样?你能告诉我怎么做不?
/*file src.s*/
.global t
.global tptr
t:
    .word 0
    .word 0
    .word 0
    .word 0

tptr:
    .word 0
    .word 0

/*file asm.c*/
struct tmp{
    int a;
    int b;
};

extern struct tmp *t;
extern long tptr;

int main()
{
    t=tptr;
    t->a=1;
    t->b=2;
    return 0;
}

1.在.global 前面加.data,表明下面的是数据段.

2.

t:
  .word 0
  .word 0

tptr:
  .word 0
  .word 0
  .word 0
  .word 0

你要搞清楚哪个是指针,哪个是结构体.名字也要起好,不要自己骗自己. 像tptr这种变量名,你自己都搞不清楚他是指针还是结构.

3.t = (struct tmp *)(&tptr);

4.好好看看我写的那些.我自己写的时候都从查at&t语法开始,到解决,差不多也要10来20分钟.

5.不建议再搞这种东西.现在的结构体tmp是对齐的, 如果不对齐,问题更多.

0
中山野鬼
中山野鬼

楼主,汇编里,没有指针的概念。只有空间和数值的概念。是否用于“指针”(高级语言里的)用途,在于你对存储的数值的理解。

你 t = tptr ,那么 实际就是

tptr:
    .word 0
    .word 0

里的值被传递到了

t:
    .word 0
    .word 0

里。

你这里没有任何地址获取,自然不对。

extern struct tmp *t;
extern long tptr;

这个是C语言对空间的界定(或者说C编译器如何理解t ,tptr空间是什么类型数据)。和汇编无关。

返回顶部
顶部