从汇编角度看C语言类型转换

最近在看《Computer Systems--A Programmer‘s Perspective》觉得有关C语言指针转换部分很有意思,虽然以前常使用类型转化可是却不知道底层(编译器?)到底怎么做的,于是从汇编角度学习了一下。使用工具GNU gcc-4.4.5,vim-7.2 ,Ubuntu10.10

假如如下定义类型v和指针p,且使用类型转化:

 

假如sizeof(src_t) > sizeof(dest_t),那么直接截取src_t中的低字节给dest_t。例如从int a转化为char b,由于这些局部变量都会存在stack上,那么就会有如下代码:可以看到就是简单的截取大变量的低字节部分给小的变量。注意其中设计到寄存器间接寻址。

 

int main()
{
    int a = 4;
    char *b;
    *b = (char)a;
}//gcc -S file.c
/*Assembly*/
movl $4,-4(%ebp)
movl -4(%ebp),%eax  #4 --> %eax
movl %eax,%edx      #4 --> %edx
movl -8(%esp),%eax  #把要存放结果的地址给%eax
movb %dl,(%eax)     #类型转化


假如sizeof(src_t) < sizeof(dest_t),就稍微复杂一点了,设计到高位扩展的问题,也就是如何补齐大变量大于小变量的那一部分。也可以使用指令movs(按源操作数符号位扩展)和movz(按零扩展)系列。

(1)如果srt_t是无符号的数,如unsigned转化为long long可以看到仅仅是把高位全部清0了。当然如果dest_t 也是无符号数于此相同,见下面:

int main()
{
    int a = 4;
    long long *b;
    b = (long long)a; 
}//gcc -S
/*Assembly*/
movl $4,12(%esp)
movl 12(%esp),%eax  #4 --> %eax
movl $0,%edx        #0 --> %edx
movl 8(%esp),%ecx   #%ecx存放%esp+8中的指针,即*b存放在%esp+8中
movl %eax,(%ecx)    #4 --> %esp+8中指针指向的地址中
movl %edx,4(%ecx)   #再把上面所说的地址中的高4字节清0


(2)如果srt_t是有符号数,而dest_t是无符号数,比如int 转化为unsigned long long,那么结果任然是有符号数,也即是不可能从小的有符号数转化得到大的无符号数:而dest_t如果也有符号则类似。

 

结论:唯一值得注意的就是可能有时候会出现char --> unsigned int的情形,那么是得不到正确结果的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值