鱼C论坛

 找回密码
 立即注册
楼主: oggplay

[技术交流] 每日一练!从零开始学习。。。。。。

[复制链接]
 楼主| 发表于 2014-5-12 22:48:01 | 显示全部楼层
=============整数看完,接着浮点数了==============
2.png
3.png

[b]例题:将1234510转换为二进制浮点12345.0 IEEE表示,并利用show_float()函数验证是否正确。

1234510=[11000000111001],将二进制小数点左移13位,于是我们得到规约化表示
[/b]1.10000001110012×2^13。根据IEEE表示,去掉小数点前面的1,并在末尾添加10个0,来构造小数位,得到二进制[10000001110010000000000]。13加32位浮点偏置量127=140,140二进制表示[10001100]。加上符号位0,我们就得到二进制的浮点表示[01000110010000001110010000000000]。那么单精度浮点值12345.0十六进制就是0x4640E400。
4.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-5-14 22:19:27 | 显示全部楼层
本帖最后由 oggplay 于 2014-5-14 22:59 编辑

***IEEE浮点运算(包括其中阿贝尔群)先忽略不看。:dizzy:
======================================
所有C语言版本提供两种不同的浮点数据类型:float和double。C语言标准不要求机器使用IEEE浮点,所以没有标准的方式或者得到诸如-0、正无穷,负无穷、NaN之类的特殊值。大多数系统提供了include文件和读取这些特征的过程库,但是细节各不相同。例如GCC会定义常数INFINITY和NAN。

#define _GNU_source 1
#include <math.h>

较新版本包括C99,包含long double数据类型。大多数编译器认为等价于double。不过对于intel兼容机,GCC用80位格式来实现这种数据类型,提供了比64位格式大的多的取值精度(学过80386汇编的应该清楚,IA32系列如intel、amd,浮点寄存器 st0,st1....st7)。
=======================================
以下int为32位:
*从int转换成float,数字不会溢出,但是可能被舍入
*从int或float转换成double,不受影响
*从double转换成float,可能溢出成正无穷或负无穷或舍入。
*从float或者double转换成int,值会向零舍入或溢出。例如1.999被转换成1,而-1.999将被转换成-1。从浮点数到整数的转换,如果不能为浮点数找到一个合理的整数近似值,就会产生一个不确定值(intel兼容处理器指定位模式[100...00]2)。因此(int)+1e10会得到-21483648,即从一个正值变成了一个负值。C标准并没有指定溢出结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-5-15 14:30:00 | 显示全部楼层
加油{:1_1:}{:1_1:} 支持一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-5-28 17:00:10 | 显示全部楼层
本帖最后由 oggplay 于 2014-5-28 17:20 编辑

第一部分第二章结束,课后练习继续中,下面开始第三章
===========================================
AT&T汇编终于派上用场。
1.png
2.png
char-->int                         movsbl   %al,(%edx)
char-->unsigned                movsbl   %al,(%edx)
unsigned char-->int           movzbl   %al,(%edx)
int-->char                         movb     %al,(%edx)
unsigned-->unsigned char  movb     %al,(%edx)
unsigned-->int                  movl     %eax,(%edx)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-5-31 10:25:51 | 显示全部楼层
本帖最后由 oggplay 于 2014-5-31 10:27 编辑

考虑下面的C函数原型,其中num_t是typedef声明的数据类型。
  1. void store_prod(num_t *dest, unsigned x, num_t y) {
  2.    *dest=x*y;
  3. }
复制代码

gcc 产生以下汇编代码来实现计算主体:
  1.   movl 12(%ebp), %eax
  2.   movl 20(%ebp), %ecx
  3.   imull %eax, %ecx
  4.   mull 16(%ebp)
  5.   leal  (%ecx,%edx), %edx
  6.   movl 8(%ebp), %ecx
  7.   movl %eax, (%ecx)
  8.   movl %edx, 4(%ecx)
复制代码

可以看到,这段代码需要读两次内存来取参数(第2行,第4行),两次乘法(第3、第4),以及两次内存写来存储结果(第7、第8)
A.num_t是什么数据类型?
B.描述计算乘积的算法,验证其正确性。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-5-31 15:31:58 | 显示全部楼层
有什么用?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-6 11:16:03 | 显示全部楼层
本帖最后由 oggplay 于 2014-6-6 21:44 编辑

控制,条件传送部分
根据汇编代码补充C代码:
  1. int test (int x, int y) {
  2.           int val = ________;
  3.           if (_____) {
  4.                if (_______)
  5.                     val = _______;
  6.                else
  7.                     val = _______;
  8.                    }  
  9.           else if (______)
  10.                   val = ________;
  11.       return val;
  12. }
复制代码



GCC产生如下的汇编代码:

x at %ebp+8 , y at %ebp+12
  1.    movl    8(%ebp), %ebx
  2.    movl    12(%ebp),%ecx
  3.    testl   %ecx, %ecx
  4.    jle     .L2
  5.    movl    %ebx, %edx
  6.    subl    %ecx, %edx
  7.    movl    %ecx, %eax
  8.    xorl    %ebx, %eax
  9.    cmpl    %ecx, %ebx
  10.    cmovl   %edx, %eax     
  11.    jmp   .L4
  12. .L2:
  13.    leal    0(,%ebx,4), %edx
  14.    leal    (%ecx, %ebx), %eax
  15.    cmpl    $-2, %ecx
  16.    cmovage  %edx, %eax
  17. .L4:
复制代码
=============================================
以上是书本32位GCC逻辑,与本人64位clang逻辑已有很大不同
  1.          movl        %edi, -4(%rbp)
  2.          movl        %esi, -8(%rbp)
  3.          movl        -4(%rbp), %esi
  4.          shll        $2, %esi
  5.          movl        %esi, -12(%rbp)
  6.          cmpl        $0, -8(%rbp)
  7.          jle        .LBB0_5

  8.          movl        -4(%rbp), %eax
  9.          cmpl        -8(%rbp), %eax
  10.          jge        .LBB0_3

  11.          movl        -4(%rbp), %eax
  12.          subl        -8(%rbp), %eax
  13.          movl        %eax, -12(%rbp)
  14.          jmp        .LBB0_4
  15. .LBB0_3:
  16.           movl        -4(%rbp), %eax
  17.           xorl        -8(%rbp), %eax
  18.           movl        %eax, -12(%rbp)
  19. .LBB0_4:
  20.            jmp        .LBB0_8
  21. .LBB0_5:
  22.            cmpl        $-2, -8(%rbp)
  23.            jge        .LBB0_7

  24.            movl        -4(%rbp), %eax
  25.            addl        -8(%rbp), %eax
  26.            movl        %eax, -12(%rbp)
  27. .LBB0_7:
  28.            jmp        .LBB0_8
  29. .LBB0_8:
  30.            movl        -12(%rbp), %eax
  31.   
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-6 17:04:09 | 显示全部楼层
看不懂啊  郁闷呢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-7 16:55:27 | 显示全部楼层
能坚持????
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-7 22:57:56 | 显示全部楼层
每日一练,一练一日。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-8 22:07:53 | 显示全部楼层
本帖最后由 oggplay 于 2014-6-8 22:13 编辑

do-while,while语句学完然后是swtich语句:
  1. int switch_eg(int x , int n){
  2.   int result=x;
  3.   
  4.   switch (n) {
  5.   
  6.   case 100:
  7.         result*=13;
  8.         break;
  9.   
  10.   case 102:
  11.         result+=100;
  12.         break;
  13.   
  14.   case 103:
  15.         result+=11;
  16.         break;
  17.   
  18.   case 104:
  19.   case 106:
  20.        result*=result;
  21.        break;      

  22.   default:
  23.     result=0;
  24.   }
  25.   return result;
  26. }
复制代码


将自己64位编译器汇编代码取代书本32位,逻辑都是一样的:

  1.         .file        "1.c"
  2.         .text
  3.         .globl        switch_eg
  4.         .align        16, 0x90
  5.         .type        switch_eg,@function
  6. switch_eg:                              # @switch_eg
  7.         .cfi_startproc
  8. # BB#0:
  9.         pushq        %rbp
  10. .Ltmp2:
  11.         .cfi_def_cfa_offset 16
  12. .Ltmp3:
  13.         .cfi_offset %rbp, -16
  14.         movq        %rsp, %rbp
  15. .Ltmp4:
  16.         .cfi_def_cfa_register %rbp
  17.         movl        %edi, -4(%rbp)
  18.         movl        %esi, -8(%rbp)
  19.         movl        -4(%rbp), %esi
  20.         movl        %esi, -12(%rbp)
  21.         movl        -8(%rbp), %esi
  22.         addl        $-100, %esi
  23.         movl        %esi, %eax
  24.         subl        $6, %esi
  25.         movq        %rax, -24(%rbp)         # 8-byte Spill
  26.         movl        %esi, -28(%rbp)         # 4-byte Spill
  27.         ja        .LBB0_5
  28. # BB#7:
  29.         movq        -24(%rbp), %rax         # 8-byte Reload
  30.         movq        .LJTI0_0(,%rax,8), %rcx
  31.         jmpq        *%rcx
  32. .LBB0_1:
  33.         imull        $13, -12(%rbp), %eax
  34.         movl        %eax, -12(%rbp)
  35.         jmp        .LBB0_6
  36. .LBB0_2:
  37.         movl        -12(%rbp), %eax
  38.         addl        $100, %eax
  39.         movl        %eax, -12(%rbp)
  40.         jmp        .LBB0_6
  41. .LBB0_3:
  42.         movl        -12(%rbp), %eax
  43.         addl        $11, %eax
  44.         movl        %eax, -12(%rbp)
  45.         jmp        .LBB0_6
  46. .LBB0_4:
  47.         movl        -12(%rbp), %eax
  48.         movl        -12(%rbp), %ecx
  49.         imull        %eax, %ecx
  50.         movl        %ecx, -12(%rbp)
  51.         jmp        .LBB0_6
  52. .LBB0_5:
  53.         movl        $0, -12(%rbp)
  54. .LBB0_6:
  55.         movl        -12(%rbp), %eax
  56.         popq        %rbp
  57.         ret
  58. .Ltmp5:
  59.         .size        switch_eg, .Ltmp5-switch_eg
  60.         .cfi_endproc
  61.         .section        .rodata,"a",@progbits
  62.         .align        8
  63. .LJTI0_0:
  64.         .quad        .LBB0_1
  65.         .quad        .LBB0_5
  66.         .quad        .LBB0_2
  67.         .quad        .LBB0_3
  68.         .quad        .LBB0_4
  69.         .quad        .LBB0_5
  70.         .quad        .LBB0_4


  71.         .section        ".note.GNU-stack","",@progbits
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-9 00:26:59 | 显示全部楼层
厚积薄发 穷且益坚
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-25 14:24:08 | 显示全部楼层
本帖最后由 oggplay 于 2014-6-25 14:29 编辑

给你个任务,检查一下C编译器为结构和联合的访问产生正确的代码,你写了下面的结构声明:
  1. typedef union {
  2.     struct   {
  3.         short  v;
  4.         short  d;
  5.         int      s;
  6. } t1;
  7.     struct {
  8.          int a[2];
  9.          char  *p;
  10.    } t2;
  11. } u_type;   
复制代码
你写了一组具有下面这种形式的函数

void get (u_type *up, TYPE *dest) {
    *dest = EXPR;
}

这组函数有不一样的访问表达式EXPR,而且根据EXPR的类型来设置目的数据类型TYPE。然后再检查编译这些函数时产生的代码,看看它们是否与你期待的一样。
假设在这些函数中,up和dest分别被加载到寄存器%eax和%edx中。填写下表中的数据类型TYPE,并用1~3条指令来计算表达式,将结果存储在dest中。试着只使用%edx和%eax,不够时再使用%ecx。


11.png


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-25 15:19:38 | 显示全部楼层
这一小节比较生疏,但是又很重要,不得不分享一下。

数据对齐:
11.png
12.png
13.png
14.png



小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-25 22:52:41 | 显示全部楼层
这是要探究一些底层的东西?还没仔细看。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-6-27 15:00:44 | 显示全部楼层
本帖最后由 oggplay 于 2014-6-27 16:24 编辑

http://bbs.fishc.com/thread-48826-1-1.html 这是栈溢出的一个例子。以下是限制栈溢出的几种策略。



1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png
10.png




小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-27 15:49:26 | 显示全部楼层
楼主加油!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-27 16:59:40 | 显示全部楼层
越来越搞不懂了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-27 17:25:56 | 显示全部楼层

祝坚持!厚积薄发~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-6-27 22:26:01 | 显示全部楼层
      过来看看啊 好东西
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-12 16:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表