Aug 13 2010

Linux下写动态链接库.so

Category: Uncategorizedwuxicn @ 9:54 PM

Linux下的动态链接库是.so文件,即:Shared Object,下面是一个简单的例子说明如何写.so以及程序如何动态载入.so中的函数和对象。

testso.h:

#ifndef _TESTSO_H
#define _TESTSO_H
extern "C" {
    int myadd(int a, int b);
    typedef int myadd_t(int, int); // myadd function type
}
#endif // _TESTSO_H

testso.cpp:

#include "testso.h"

extern "C"
int myadd(int a, int  b)
{
    return a + b;
}

编译so:

g++  -shared  -fPIC  -o testso.so testso.cpp

注意,-shared参数和-fPIC参数非常重要:
-shared 告诉gcc要生成的是动态链接库;
-fPIC 告诉gcc生成的生成的代码是非位置依赖的,方面的用于动态链接。

Continue reading “Linux下写动态链接库.so”

Tags: , , ,


Apr 25 2010

[zz]Guide: Function Calling Conventions

Category: Uncategorizedwuxicn @ 9:55 PM

Guide: Function Calling Conventions

GCC follows certain rules in generating and calling its functions. If you are writing portable C or C++ code, you never need to know about these rules. However, if you are writing assembly language or nonportable code that depends on these rules, you need to know what they are. This document attemps to describe them, and gives some examples.

Notes

This document assumes a familiarity with assembly language. The assembler code used here is written in the AT&T syntax, as used by GNU as. If you’re using an Intel-syntax assembler, like nasm, you’ll have to translate appropriately.

What’s described here are GCC’s standard calling conventions. Many can be changed by using options like -mregparm, but that’s outside the scope of this document.

These conventions apply to C. C++ introduces several additional complications (such as class pointers and name mangling), some of which can change between compiler versions. Thus, I suggest that asm functions called from C++ code be declared as extern "C". This will cause C calling conventions to be used.

Writing Assembly-Language Functions

Naming

In DJGPP, a function’s assembly-language name is the same as its C name, with an underscore (“_“) prepended. Thus, the C function foo would be named _foo in assembly language. (This is in fact true for all symbol names, such as variables.) C++ has some much more complicated rules.

Registers

GCC requires that some registers not change across a function call. If you want to use these registers in an assembly function, you must save and restore their values. They are:

  • %ebx
  • %esi
  • %edi
  • %ebp
  • The segment registers %ds%es and %ss

Other registers are available for your use (though some have other special uses; read on).

  • Integers (of any size up to 32 bits) and pointers are returned in the %eax register.
  • Floating point values are returned in the 387 top-of-stack register, st(0).
  • Return values of type long long int are returned in %edx:%eax (the most significant word in %edx and the least significant in %eax).
  • Returning a structure is complicated and rarely useful; try to avoid it. (Note that this is different from returning a pointer to a structure.)

If your function returns void (e.g. no value), the contents of these registers are not used.

          Last argument
	  ...
4(%esp)	  First argument
(%esp)    Return address

  • Integers up to 32 bits and pointers are pushed as a single longword.
  • long long int is pushed as two longwords; the least significant is pushed last (and so is located first in memory).
  • float and double are pushed as a double-precision value, occupying 8 bytes.
  • long double is pushed as an extended-precision value followed by 2 bytes of padding, totalling 12 bytes.
  • As before, structures are more complicated and best avoided.

These rules also apply to functions which take a variable number of arguments (like printf). As with any variadic function, the function must find its own way of determining how many arguments were actually passed (usually based on one of the required args).

The stack below the return address is available for temporary storage, but be sure to decrement %esp appropriately. Memory below %esp may be overwritten asynchronously, by interrupt handlers and such. Restore its value when exiting, so that the return works correctly. You may also push and pop at will.

You may modify your arguments in place if you wish; they will not be reused by the caller. Do not, however, attempt to pop them; the caller handles this.

Calling C Functions From Assembly Language

An assembly language function may wish to call a function written in C, either your own or one from the standard library. The same rules already explained apply; you just see them from the other side.

First, you push the function’s arguments (if any) onto the stack, last argument first. See above for the formats used. (Floating point values are usually most easily handled by making space on the stack and then executing a store instruction; i.e. subl $8,%esp; fstpl (%esp).)

Use a simple call instruction to call the function.

You are responsible for removing the arguments you have pushed. They may have changed, so you may not reuse them. You need not, however, discard them at once; it may be more convenient when calling several functions to leave the arguments on the stack and pop them all together at the end. addl n,%esp is an efficient way to do this. It may also be convenient in this case to use %ebp as a frame pointer, since it need not change all the time. (The C compiler does this.)

The return value may be found as detailed above.

Expect the registers %eax%ecx, and %edx, as well as the floating-point stack, to have changed. Standard library functions may modify the %gs register, and the_far* functions may modify %fs. Other registers will be preserved.

Conclusion

These are the basic calling conventions used by GCC; however, there are special cases, optional modifications, etc. that can apply in situations not covered here. In this case, gcc -S is your best friend – from assembly output, you can usually figure out the rules. Also helpful is the GCC source: see i386.h and i386.md inconfig/i386. They are well commented.

Examples

(略,见原文)

原文:http://www.delorie.com/djgpp/doc/ug/asm/calling.html

Tags: , ,


Apr 10 2010

Win32 内存中的栈与函数调用约定(

Category: Uncategorizedwuxicn @ 12:56 AM

注意:本文是针对Win32的,对linux下的gcc不适用!

1. 栈 Stack

在内存中,栈(Stack)是从高地址往低地址增长的[1](从上到下布局的),例如:

1052h |------| < -- sp
1051h |------|                /\
1050h |------| push ||    pop ||
104Fh |------|      \/
104Eh |------|

即当前sp在1052h位置,push了1 Byte以后,sp = sp - 1 即:1051h。

并且,数据存放时按照我们正常的逻辑存放,高地址存放数据的高字节、低地址存放数据的低字节,例如:
当前sp=1052h, push word 0x1234 时,先将高字节0x12存入sp-1的位置(1051h),再将0x34存入sp-2位置(1050h),然后sp = sp - 2 (sp变为1050h) [1].

2. 函数调用约定 Calling Convention

Continue reading "Win32 内存中的栈与函数调用约定("

Tags: , , , ,


Mar 30 2010

Syscall numbers on Mac (BSD)

Category: Uncategorizedwuxicn @ 10:54 PM

Path: /usr/include/sys/syscall.h

#define	SYS_syscall        0
#define	SYS_exit           1
#define	SYS_fork           2
#define	SYS_read           3
#define	SYS_write          4
#define	SYS_open           5
#define	SYS_close          6
#define	SYS_wait4          7

Continue reading “Syscall numbers on Mac (BSD)”

Tags: , , ,


Feb 02 2010

【转】50个c/c++源代码网站

Category: Uncategorizedwuxicn @ 8:09 PM

C/C++是最主要的编程语言。这里列出了50名优秀网站和网页清单,这些网站提供c/c++源代码。这份清单提供了源代码的链接以及它们的小说明。我已尽力包括最佳的C/C++源代码的网站。这不是一个完整的清单,您有建议可以联系我,我将欢迎您的建议,以进一步加强这方面的清单。

1、http://snippets.dzone.com/tag/c/ –数以千计的有用的C语言源代码片段
2、http://www.hotscripts.com/category/c-cpp/scripts-programs/ Hotscripts –提供数以百计的C和C++脚本和程序。所有程序都分为不同的类别。
3、http://www.planetsourcecode.com/vb/default.asp?lngWId=3 –超过万行C和C++免费的源代码
4、http://freshmeat.net/browse/164/ –超过9000个C编写的项目。
5、http://www.daniweb.com/code/c.html –DANIWEB提供的实用代码段 。 Continue reading “【转】50个c/c++源代码网站”

Tags: ,


Jan 21 2010

C/C++一些奇怪的语法

Category: Uncategorizedwuxicn @ 10:28 PM

1、C语言中的数组

在C/C++中,a[10] 可以写成 10[ a ]

“Hello World”[i] 也可以写成 i["Hello World"]

这样的特性是不是很怪异?如果你想知道为什么的话,你可以看看本站的这篇文章——《C语言的谜题》中的第12题。
Continue reading “C/C++一些奇怪的语法”

Tags: ,


Nov 17 2009

do while 的两个小技巧

Category: Uncategorizedwuxicn @ 1:01 PM

do {

}
while (0); // while (false)
的一点有用的小技巧:
Continue reading “do while 的两个小技巧”

Tags: ,


Nov 16 2009

一种不常见的数组元素或结构成员的初始化方式

Category: Uncategorizedwuxicn @ 7:52 PM

struct ST {
int a;
int b;
int c;
};

一般初始化方式:
int arr[10] = { 1, 3 }; // a[0] = 1; a[1] = 3;
struct ST s = { 5, 7 }; // s.a = 5; s.b = 7;

指定元素的初始化方法:
int arr[10] = { [5] = 7 }; // a[5] = 7;
struct ST s = { .b = 57 }; // s.b = 57;

struct ST sarr[10] = { [1].c = 57 }; // sarr[1].c = 57;


呵呵,是不是很像 解释型语言?

Tags:


Nov 16 2009

C/C++中复杂的指针的理解方法

Category: Uncategorizedwuxicn @ 1:25 PM

C/C++中的指针是令所有 C/C++ programmer 都望而生畏的东西,有很多难点。其中,光是对复杂的指针定义就很难理解。今天看到www.jluopen.org论坛里面jcwkyl发了一篇关于《C++编程思想》里复杂的函数指针理解方法的帖子(http://www.jluopen.org/bbs/thread-137-1-1.html),里面有这样两个复杂的指针定义:
Continue reading “C/C++中复杂的指针的理解方法”

Tags: ,


Nov 09 2009

应该在何时使用assert?

Category: Uncategorizedwuxicn @ 9:39 PM

很多人都拿不准什么时候该使用assert来判断函数的参数是否有效。例如:一个函数char* f(char* x),是应该 assert(x); 还是:if (x==NULL) return NULL; ?其实到底该用assert还是用if的道理很简单,下面我来说一下。

首先必须明确一点,出于鲁棒性,有些函数参数(如指针)必须得进行检查(用assert或者if)。

然后就是该用assert还是用if了?这个得根据函数的定义域来定。例如,有一个求平方根的函数double sqrt(double x);

如果用assert(x >= 0); 来进行参数检查,则表明函数的定义域是:[0, +Infinite) ;但如果用if (x < 0) return 0; 来检查,则函数的定义域就是 (-Infinite, +Infinite)了!所以这两函数在逻辑上不是同一个函数。所以,如果让你实现一个memcpy(dst, src, len)函数,如果是:assert(dst); assert(src); 则表明这个memcpy只能接受非空的指针参数;而如果写成if (dst == NULL) return NULL;则表明,memcpy可以接受空指针参数,只是你要是将空指针作为参数,则返回NULL。

最后还要补充说明一点是,assert只是在DEBUG版本下才有用的,有时候还用作debug时检查一些变量的值。

Tags: ,


Next Page »