计算机系统基础第四篇-4 数据的存储和运算

  1. 整数的编码-真值和机器数
    带符号整数按照补码进行真值表示;无符号整数按照原码进行真值表示。
    举个例子:
#include <iostream>
#include <stdio.h>

int main()
{
    int ai = 100;
    int bi = 2147483648;
    int ci = -100;
    unsigned au = 100;
    unsigned bu = 2147483648;
    unsigned cu = -100;

    printf("ai=%d, bi=%d, ci=%d\n",ai, bi, ci);
    printf("au=%u, bu=%u, cu=%u\n",ai, bi, ci);
    return 0;
}

运行结果为:

ai=100, bi=-2147483648, ci=-100
au=100, bu=2147483648, cu=4294967196

反汇编后:

int main()
{
  400706:   55                      push   %rbp
  400707:   48 89 e5                mov    %rsp,%rbp
  40070a:   48 83 ec 20             sub    $0x20,%rsp
    int ai = 100;
  40070e:   c7 45 e8 64 00 00 00    movl   $0x64,-0x18(%rbp)
    int bi = 2147483648;
  400715:   c7 45 ec 00 00 00 80    movl   $0x80000000,-0x14(%rbp)
    int ci = -100;
  40071c:   c7 45 f0 9c ff ff ff    movl   $0xffffff9c,-0x10(%rbp)
    unsigned au = 100;
  400723:   c7 45 f4 64 00 00 00    movl   $0x64,-0xc(%rbp)
    unsigned bu = 2147483648;
  40072a:   c7 45 f8 00 00 00 80    movl   $0x80000000,-0x8(%rbp)
    unsigned cu = -100;
  400731:   c7 45 fc 9c ff ff ff    movl   $0xffffff9c,-0x4(%rbp)

    printf("ai=%d, bi=%d, ci=%d\n",ai, bi, ci);
  400738:   8b 4d f0                mov    -0x10(%rbp),%ecx
  40073b:   8b 55 ec                mov    -0x14(%rbp),%edx
  40073e:   8b 45 e8                mov    -0x18(%rbp),%eax
  400741:   89 c6                   mov    %eax,%esi
  400743:   bf 54 08 40 00          mov    $0x400854,%edi
  400748:   b8 00 00 00 00          mov    $0x0,%eax
  40074d:   e8 5e fe ff ff          callq  4005b0 <printf@plt>
    printf("au=%u, bu=%u, cu=%u\n",ai, bi, ci);
  400752:   8b 4d f0                mov    -0x10(%rbp),%ecx
  400755:   8b 55 ec                mov    -0x14(%rbp),%edx
  400758:   8b 45 e8                mov    -0x18(%rbp),%eax
  40075b:   89 c6                   mov    %eax,%esi
  40075d:   bf 69 08 40 00          mov    $0x400869,%edi
  400762:   b8 00 00 00 00          mov    $0x0,%eax
  400767:   e8 44 fe ff ff          callq  4005b0 <printf@plt>
    return 0;
  40076c:   b8 00 00 00 00          mov    $0x0,%eax
}

2 浮点数的编码-真值和机器数
浮点数使用IEEE 754标准进行编码

#include <iostream>
#include <stdio.h>

int main()
{
    int ai = 100;
    int bi = -100;
    float af = 100;
    float bf = -100;

    printf("ai=%d, bi=%d\n",ai, bi);
    printf("af=%f, bf=%f\n",af, bf);
    return 0;
}

反汇编后结果为:

int main()
{
  400706:   55                      push   %rbp
  400707:   48 89 e5                mov    %rsp,%rbp
  40070a:   48 83 ec 10             sub    $0x10,%rsp
    int ai = 100;
  40070e:   c7 45 f0 64 00 00 00    movl   $0x64,-0x10(%rbp)
    int bi = -100;
  400715:   c7 45 f4 9c ff ff ff    movl   $0xffffff9c,-0xc(%rbp)
    float af = 100;
  40071c:   f3 0f 10 05 3c 01 00    movss  0x13c(%rip),%xmm0        # 400860 <_IO_stdin_used+0x20>
  400723:   00
  400724:   f3 0f 11 45 f8          movss  %xmm0,-0x8(%rbp)                                             
    float bf = -100;
  400729:   f3 0f 10 05 33 01 00    movss  0x133(%rip),%xmm0        # 400864 <_IO_stdin_used+0x24>
  400730:   00
  400731:   f3 0f 11 45 fc          movss  %xmm0,-0x4(%rbp)

    printf("ai=%d, bi=%d\n",ai, bi);
  400736:   8b 55 f4                mov    -0xc(%rbp),%edx
  400739:   8b 45 f0                mov    -0x10(%rbp),%eax
  40073c:   89 c6                   mov    %eax,%esi
  40073e:   bf 44 08 40 00          mov    $0x400844,%edi
  400743:   b8 00 00 00 00          mov    $0x0,%eax
  400748:   e8 63 fe ff ff          callq  4005b0 <printf@plt>
    printf("af=%f, bf=%f\n",af, bf);
  40074d:   f3 0f 5a 4d fc          cvtss2sd -0x4(%rbp),%xmm1
  400752:   f3 0f 5a 45 f8          cvtss2sd -0x8(%rbp),%xmm0
  400757:   bf 52 08 40 00          mov    $0x400852,%edi
  40075c:   b8 02 00 00 00          mov    $0x2,%eax
  400761:   e8 4a fe ff ff          callq  4005b0 <printf@plt>
    return 0;
  400766:   b8 00 00 00 00          mov    $0x0,%eax
}

这里面获取浮点数用到了movss指令,具体可以看这个帖子:
SSE指令集
使用gdb来看看机器数

(gdb) b main
Breakpoint 1 at 0x40070e: file float.cpp, line 6.
(gdb) r
Starting program: /home/aitian/myProject/OS/day3/float 

Breakpoint 1, main () at float.cpp:6
6	    int ai = 100;
(gdb) i r rip
rip            0x40070e	0x40070e <main()+8>
(gdb) s
7	    int bi = -100;
(gdb) s
8	    float af = 100;
(gdb) s
9	    float bf = -100;
(gdb) s
11	    printf("ai=%d, bi=%d\n",ai, bi);
(gdb) i r rip
rip            0x400736	0x400736 <main()+48>
(gdb) i r rsp rbp
rsp            0x7fffffffd7a0	0x7fffffffd7a0
rbp            0x7fffffffd7b0	0x7fffffffd7b0
(gdb) x/4xw $rsp
0x7fffffffd7a0:	0x00000064	0xffffff9c	0x42c80000	0xc2c80000

可以看出ai,bi这两个整数对应的机器数是0x00000064 0xffffff9c
af,bf这两个浮点数对应的机器数是0x42c80000 0xc2c80000

3 数据存储排列方式和对齐方式
不同的类型占用的宽度是不一样的。
数据的排列方式就是大端小端.
在这里插入图片描述
比如我的机器就是小端的:

(gdb) i r rsp rbp
rsp            0x7fffffffd7a0	0x7fffffffd7a0
rbp            0x7fffffffd7b0	0x7fffffffd7b0
(gdb) x/16xb $rsp
0x7fffffffd7a0:	0x90	0xd8	0xff	0xff	0xff	0x64	0x64	0x00
0x7fffffffd7a8:	0x64	0x00	0x00	0x00	0x78	0x56	0x34	0x12

数据的对齐方式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3 整数类型之间的转换
第一种情况:宽度相同
在这里插入图片描述
第二种情况:短的给长的
在这里插入图片描述
第三种情况:长的给短的
在这里插入图片描述
4 整数和浮点数的转换
整数和浮点数的转换是在编码格式上的转换,而不是机器数上的直接复制。
举个例子:

#include <stdio.h>

int main()
{
    int i1 = 0x7fffffff;
    int i2;
    int itemp;

    float f1=0x987654321;
    float f2;
    float ftemp;

    ftemp = i1;
    i2 = ftemp;

    itemp = f1;
    f2 = itemp;
    printf("i1=%d,i2=%d\n,f1=%f,f2=%f\n", i1,i2,f1,f2);
    return 0;
}

运行后结果为:

i1=2147483647,i2=-2147483648
,f1=40926265344.000000,f2=-2147483648.000000

分析一下原因:
对应第一个转换
在这里插入图片描述
对应第二个转换
在这里插入图片描述
5.整数加减运算
由于补码的作用,整数减法也是按照加法计算的。整数加减注意溢出。
怎么判断整数加减是否有溢出存在呢:
对于无符号运算:
在这里插入图片描述
而对于带符号整数的加减运算:
在这里插入图片描述
在这里插入图片描述
6.浮点数运算
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
浮点数的真值与机器数的互相转化:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
举个例子如下:

#include <stdio.h>

int main()
{
    // 无穷大
    float f1 = 4e38;
    float f2 = 5e38;
    float f3 = 6e38;

    // 负无穷大
    float f4 = -4e38;
    float f5 = -5e38;
    float f6 = -6e38;

    // 0, -0
    float f7 = 0;
    float f8 = -f7;

    // 规格化数
    float f9 = 5.0;
    float f10 = 0.1;
    float f11 = -5;
    float f12 = -0.1;

    // 非规格化数
    float f13 = 1e-40;
    float f14 = -1e-40;
    
    // 无定义数
    float f15 = f1 + f4;
    float f16 = -f15;

    // 除以0,无穷大
    float f17 = f9/f7;

    return 0;
}

反汇编后:

int main()
{
  4004d6:   55                      push   %rbp
  4004d7:   48 89 e5                mov    %rsp,%rbp
    // 无穷大
    float f1 = 4e38;
  4004da:   f3 0f 10 05 7e 01 00    movss  0x17e(%rip),%xmm0        # 400660 <_IO_stdin_used+0x10>
  4004e1:   00 
  4004e2:   f3 0f 11 45 bc          movss  %xmm0,-0x44(%rbp)
    float f2 = 5e38;
  4004e7:   f3 0f 10 05 71 01 00    movss  0x171(%rip),%xmm0        # 400660 <_IO_stdin_used+0x10>
  4004ee:   00 
  4004ef:   f3 0f 11 45 c0          movss  %xmm0,-0x40(%rbp)
    float f3 = 6e38;
  4004f4:   f3 0f 10 05 64 01 00    movss  0x164(%rip),%xmm0        # 400660 <_IO_stdin_used+0x10>
  4004fb:   00 
  4004fc:   f3 0f 11 45 c4          movss  %xmm0,-0x3c(%rbp)

    // 负无穷大
    float f4 = -4e38;
  400501:   f3 0f 10 05 5b 01 00    movss  0x15b(%rip),%xmm0        # 400664 <_IO_stdin_used+0x14>
  400508:   00 
  400509:   f3 0f 11 45 c8          movss  %xmm0,-0x38(%rbp)
    float f5 = -5e38;
  40050e:   f3 0f 10 05 4e 01 00    movss  0x14e(%rip),%xmm0        # 400664 <_IO_stdin_used+0x14>
  400515:   00 
  400516:   f3 0f 11 45 cc          movss  %xmm0,-0x34(%rbp)
    float f6 = -6e38;
  40051b:   f3 0f 10 05 41 01 00    movss  0x141(%rip),%xmm0        # 400664 <_IO_stdin_used+0x14>
  400522:   00 
  400523:   f3 0f 11 45 d0          movss  %xmm0,-0x30(%rbp)

    // 0, -0
    float f7 = 0;
  400528:   66 0f ef c0             pxor   %xmm0,%xmm0
  40052c:   f3 0f 11 45 d4          movss  %xmm0,-0x2c(%rbp)
    float f8 = -f7;
  400531:   f3 0f 10 4d d4          movss  -0x2c(%rbp),%xmm1
  400536:   f3 0f 10 05 32 01 00    movss  0x132(%rip),%xmm0        # 400670 <_IO_stdin_used+0x20>
  40053d:   00 
  40053e:   0f 57 c1                xorps  %xmm1,%xmm0
  400541:   f3 0f 11 45 d8          movss  %xmm0,-0x28(%rbp)

    // 规格化数
    float f9 = 5.0;
  400546:   f3 0f 10 05 32 01 00    movss  0x132(%rip),%xmm0        # 400680 <_IO_stdin_used+0x30>
  40054d:   00 
  40054e:   f3 0f 11 45 dc          movss  %xmm0,-0x24(%rbp)
    float f10 = 0.1;
  400553:   f3 0f 10 05 29 01 00    movss  0x129(%rip),%xmm0        # 400684 <_IO_stdin_used+0x34>
  40055a:   00 
  40055b:   f3 0f 11 45 e0          movss  %xmm0,-0x20(%rbp)
    float f11 = -5;
  400560:   f3 0f 10 05 20 01 00    movss  0x120(%rip),%xmm0        # 400688 <_IO_stdin_used+0x38>
  400567:   00 
  400568:   f3 0f 11 45 e4          movss  %xmm0,-0x1c(%rbp)
    float f12 = -0.1;
  40056d:   f3 0f 10 05 17 01 00    movss  0x117(%rip),%xmm0        # 40068c <_IO_stdin_used+0x3c>
  400574:   00 
  400575:   f3 0f 11 45 e8          movss  %xmm0,-0x18(%rbp)

    // 非规格化数
    float f13 = 1e-40;
  40057a:   f3 0f 10 05 0e 01 00    movss  0x10e(%rip),%xmm0        # 400690 <_IO_stdin_used+0x40>
  400581:   00 
  400582:   f3 0f 11 45 ec          movss  %xmm0,-0x14(%rbp)
    float f14 = -1e-40;
  400587:   f3 0f 10 05 05 01 00    movss  0x105(%rip),%xmm0        # 400694 <_IO_stdin_used+0x44>
  40058e:   00 
  40058f:   f3 0f 11 45 f0          movss  %xmm0,-0x10(%rbp)
    
  40058f:   f3 0f 11 45 f0          movss  %xmm0,-0x10(%rbp)
    
    // 无定义数
    float f15 = f1 + f4;
  400594:   f3 0f 10 45 bc          movss  -0x44(%rbp),%xmm0
  400599:   f3 0f 58 45 c8          addss  -0x38(%rbp),%xmm0
  40059e:   f3 0f 11 45 f4          movss  %xmm0,-0xc(%rbp)
    float f16 = -f15;
  4005a3:   f3 0f 10 4d f4          movss  -0xc(%rbp),%xmm1
  4005a8:   f3 0f 10 05 c0 00 00    movss  0xc0(%rip),%xmm0        # 400670 <_IO_stdin_used+0x20>
  4005af:   00 
  4005b0:   0f 57 c1                xorps  %xmm1,%xmm0
  4005b3:   f3 0f 11 45 f8          movss  %xmm0,-0x8(%rbp)

    // 除以0,无穷大
    float f17 = f9/f7;
  4005b8:   f3 0f 10 45 dc          movss  -0x24(%rbp),%xmm0
  4005bd:   f3 0f 5e 45 d4          divss  -0x2c(%rbp),%xmm0

先看看f1,f2,f3这三个无穷大:

(gdb) x/3xw $rbp-0x3c
0x7fffffffd774:	0x7f800000	0xff800000	0xff800000

看看f4,f5,f6这三个负无穷大:

(gdb) x/3xw $rbp-0x30
0x7fffffffd780:	0xff800000	0x00000000	0x80000000

再看正零和负零:

(gdb) x/2xw $rbp-0x2c
0x7fffffffd784:	0x00000000	0x80000000

其他的就不一一看了。反正和前面的规范是能对上的。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涤除而玄览

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值