10/25/2007

调用函数时,寄存器到底发生了那些变化?

linux x86 gcc3.2.3 AT&T格式的汇编

代码如下:


void
fun()
{
int a = 'A';
}

void main()
{
int b;
fun();

return;
}


编译
gcc -g -o t t.c

开始调试
[sanool@sanool ex2]$ gdb t
GNU gdb Red Hat Linux (6.0post-0.20031117.6rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) disas main
Dump of assembler code for function main:
0x08048323 : push %ebp
0x08048324 : mov %esp,%ebp
0x08048326 : sub $0x8,%esp
0x08048329 : and $0xfffffff0,%esp
0x0804832c : mov $0x0,%eax
0x08048331 : sub %eax,%esp
0x08048333 : call 0x8048314
0x08048338 : leave
0x08048339 : ret
0x0804833a : nop
0x0804833b : nop
End of assembler dump.
(gdb) disas fun
Dump of assembler code for function fun:
0x08048314 : push %ebp
0x08048315 : mov %esp,%ebp
0x08048317 : sub $0x4,%esp
0x0804831a : movl $0x41,0xfffffffc(%ebp)
0x08048321 : leave
0x08048322 : ret
End of assembler dump.

解释如下:
**当程序下一步执行 0x08048333 : call 0x8048314
esp = 0xbfffe660 (运行时)
ebp = 0xbfffe668 (运行时)
eip = 0x08048333

**然后执行 call 0x8048314 也就是
push %eip ( 相当于 sub $4 %esp 再 mov %eip %esp )
movl $0x8048314, %eip

则0xbfffe65c 处为 eip = 0x08048338
且esp = 0xbfffe65c
eip = 0x8048314
ebp = 0xbfffe668

**执行0x08048314 : push %ebp后
esp = 0xbfffe658
ebp = 0xbfffe668
0xbfffe658处的值为 ebp = 0xbfffe668

**继续0x08048315 : mov %esp,%ebp
将esp的值赋值给ebp
即 ebp = esp = 0xbfffe658

**开始执行 0x08048321 : leave 前
eip = 0x08048321
ebp = 0xbfffe658
esp = 0xbfffe654

**开始执行 0x08048321 : leave 时
即进行
movl %ebp, %esp ( 即 esp = ebp = 0xbfffe658)
pop %ebp ( 也就是 mov %esp,%ebp 再 add $4,%esp )

此时 ebp = 0xbfffe668 回到了原函数的ebp值,

**再执行 0x08048322 : ret
即 pop %eip
( 也就是 mov %esp,%eip 再 add $4,%esp )
此时 eip = 0x08048338
程序继续执行 main 中的 leave

调用fun函数结束

补充:
i reg //观察寄存器的值 (注意ebp esp eip)

x/20x $esp //查看内存中$esp(如0xbfffef50)后面的数据内容

10/15/2007

大规模并行计算

http://code.google.com/edu 可获得华盛顿大学编写的所有课程资料,以及其他用于帮助学习这一前沿技术的工具和资源。
如果想了解此类项目的意义,请观看系列讲座视频(共五部分,原是谷歌工程部实习生的学习资料),其中介绍了大规模集群计算的一些基本概念。

10/09/2007

cut、tr 等命令格式化字符串

CurreIP=$(wget http://freedns.afraid.org/dynamic/check.php -o /dev/null -O /dev/stdout | grep Detected | cut -d : -f 2 | cut -d '<' -f 1 | tr -d " ")

cat check.php :

Detected IP : 210.73.65.34, 210.73.65.77
HTTP_CLIENT_IP :
HTTP_X_FORWARDED_FOR : 210.73.65.34, 210.73.65.77
REMOTE_ADDR : 72.20.25.132

9/18/2007

vim + cscope/ctags

生成符号索引文件: cscope -Rbkq
这个命令会生成三个文件:cscope.out, cscope.in.out, cscope.po.out。
上面所用到的命令参数,含义如下:

-R: 在生成索引文件时,搜索子目录树中的代码
-b: 只生成索引文件,不进入cscope的界面
-k: 在生成索引文件时,不搜索/usr/include目录
-q: 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度

按照cscope手册上提供的方法,先产生一个文件列表,然后让cscope为这个列表中的每个文件都生成索引。
为了方便使用,编写了下面的脚本来更新cscope和ctags的索引文件:


#!/bin/sh

find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files
cscope -bkq -i cscope.files
ctags -R


这个脚本,首先使用find命令,查找当前目录及子目录中所有后缀名为".h", ".c"和".cc"的文件,并把查找结果重定向到文件cscope.files中,然后cscope根据cscope.files中的所有文件,生成符号索引文件。最后一条命令使用ctags命令,生成一个tags文件。

cscope的主页在:http://cscope.sourceforge.net
vim的主页:http://www.vim.org

9/12/2007

malloc(0) 的问题


char *p;
p = (char *)malloc(0);


以上代码没有错误,但 p 的分配的空间大小是多少呢,不确定?
至于为什么可以分配成功,看看 malloc 的说明就明白了:

malloc returns a void pointer to the allocated space,or null if there is insufficient memory available.

9/07/2007

领带的几种打法



呵呵,还不会呢,以后应该用的着。

9/06/2007

查看pci设备的方法?!

大家都知道可以使用 lspci 查看pci设备信息。PCI设备是其特定的ID号来标示的,包含vendor id, device id, subsystem等,这个ID是由一个组织统管并给各大硬件厂商分配。一般来说,一个精确的ID就唯一得确定了一种PCI设置,因此通过读取此ID就可以得知此设备究竟是什么东西。Linux发行版中的lspci工具就是做这个的。但由于发行版发行时间问题,系统自带的ID-设备对硬数据库可能比较陈旧,导致识别不出新的设备来,这是就会出现unknown device,如同上面我们看到的结果。遇到此类情况,解决方法是使用新的IDs数据库。对于Linux,有一个项目是构建公开的ID数据库,在这里:http://pciids.sourceforge.net/,可以在此网站直接下载其数据库http://pciids.sourceforge.net/pci.ids到本地,然后使用命令lspci -i path-to-pci.ids 来指定使用下载到的ID数据库来鉴别设备。