=============整数看完,接着浮点数了==============
例题:将1234510转换为二进制浮点12345.0 IEEE表示,并利用show_float()函数验证是否正确。
1234510=],将二进制小数点左移13位,于是我们得到规约化表示1.10000001110012×2^13。根据IEEE表示,去掉小数点前面的1,并在末尾添加10个0,来构造小数位,得到二进制。13加32位浮点偏置量127=140,140二进制表示。加上符号位0,我们就得到二进制的浮点表示。那么单精度浮点值12345.0十六进制就是0x4640E400。
本帖最后由 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兼容处理器指定位模式2)。因此(int)+1e10会得到-21483648,即从一个正值变成了一个负值。C标准并没有指定溢出结果。
加油{:1_1:}{:1_1:} 支持一下
本帖最后由 oggplay 于 2014-5-28 17:20 编辑
第一部分第二章结束,课后练习继续中,下面开始第三章
===========================================
AT&T汇编终于派上用场。
char-->int movsbl %al,(%edx)
char-->unsigned movsbl %al,(%edx)
unsigned char-->int movzbl %al,(%edx)
int-->char movb %al,(%edx)
unsigned-->unsigned charmovb %al,(%edx)
unsigned-->int movl %eax,(%edx)
本帖最后由 oggplay 于 2014-5-31 10:27 编辑
考虑下面的C函数原型,其中num_t是typedef声明的数据类型。
void store_prod(num_t *dest, unsigned x, num_t y) {
*dest=x*y;
}
gcc 产生以下汇编代码来实现计算主体:
movl 12(%ebp), %eax
movl 20(%ebp), %ecx
imull %eax, %ecx
mull 16(%ebp)
leal(%ecx,%edx), %edx
movl 8(%ebp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
可以看到,这段代码需要读两次内存来取参数(第2行,第4行),两次乘法(第3、第4),以及两次内存写来存储结果(第7、第8)
A.num_t是什么数据类型?
B.描述计算乘积的算法,验证其正确性。
有什么用?
本帖最后由 oggplay 于 2014-6-6 21:44 编辑
控制,条件传送部分
根据汇编代码补充C代码:
int test (int x, int y) {
int val = ________;
if (_____) {
if (_______)
val = _______;
else
val = _______;
}
else if (______)
val = ________;
return val;
}
GCC产生如下的汇编代码:
x at %ebp+8 , y at %ebp+12 movl 8(%ebp), %ebx
movl 12(%ebp),%ecx
testl %ecx, %ecx
jle .L2
movl %ebx, %edx
subl %ecx, %edx
movl %ecx, %eax
xorl %ebx, %eax
cmpl %ecx, %ebx
cmovl %edx, %eax
jmp .L4
.L2:
leal 0(,%ebx,4), %edx
leal (%ecx, %ebx), %eax
cmpl $-2, %ecx
cmovage%edx, %eax
.L4:=============================================
以上是书本32位GCC逻辑,与本人64位clang逻辑已有很大不同
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %esi
shll $2, %esi
movl %esi, -12(%rbp)
cmpl $0, -8(%rbp)
jle .LBB0_5
movl -4(%rbp), %eax
cmpl -8(%rbp), %eax
jge .LBB0_3
movl -4(%rbp), %eax
subl -8(%rbp), %eax
movl %eax, -12(%rbp)
jmp .LBB0_4
.LBB0_3:
movl -4(%rbp), %eax
xorl -8(%rbp), %eax
movl %eax, -12(%rbp)
.LBB0_4:
jmp .LBB0_8
.LBB0_5:
cmpl $-2, -8(%rbp)
jge .LBB0_7
movl -4(%rbp), %eax
addl -8(%rbp), %eax
movl %eax, -12(%rbp)
.LBB0_7:
jmp .LBB0_8
.LBB0_8:
movl -12(%rbp), %eax
看不懂啊郁闷呢
能坚持????
每日一练,一练一日。
本帖最后由 oggplay 于 2014-6-8 22:13 编辑
do-while,while语句学完然后是swtich语句:
int switch_eg(int x , int n){
int result=x;
switch (n) {
case 100:
result*=13;
break;
case 102:
result+=100;
break;
case 103:
result+=11;
break;
case 104:
case 106:
result*=result;
break;
default:
result=0;
}
return result;
}
将自己64位编译器汇编代码取代书本32位,逻辑都是一样的:
.file "1.c"
.text
.globl switch_eg
.align 16, 0x90
.type switch_eg,@function
switch_eg: # @switch_eg
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp2:
.cfi_def_cfa_offset 16
.Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp4:
.cfi_def_cfa_register %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %esi
movl %esi, -12(%rbp)
movl -8(%rbp), %esi
addl $-100, %esi
movl %esi, %eax
subl $6, %esi
movq %rax, -24(%rbp) # 8-byte Spill
movl %esi, -28(%rbp) # 4-byte Spill
ja .LBB0_5
# BB#7:
movq -24(%rbp), %rax # 8-byte Reload
movq .LJTI0_0(,%rax,8), %rcx
jmpq *%rcx
.LBB0_1:
imull $13, -12(%rbp), %eax
movl %eax, -12(%rbp)
jmp .LBB0_6
.LBB0_2:
movl -12(%rbp), %eax
addl $100, %eax
movl %eax, -12(%rbp)
jmp .LBB0_6
.LBB0_3:
movl -12(%rbp), %eax
addl $11, %eax
movl %eax, -12(%rbp)
jmp .LBB0_6
.LBB0_4:
movl -12(%rbp), %eax
movl -12(%rbp), %ecx
imull %eax, %ecx
movl %ecx, -12(%rbp)
jmp .LBB0_6
.LBB0_5:
movl $0, -12(%rbp)
.LBB0_6:
movl -12(%rbp), %eax
popq %rbp
ret
.Ltmp5:
.size switch_eg, .Ltmp5-switch_eg
.cfi_endproc
.section .rodata,"a",@progbits
.align 8
.LJTI0_0:
.quad .LBB0_1
.quad .LBB0_5
.quad .LBB0_2
.quad .LBB0_3
.quad .LBB0_4
.quad .LBB0_5
.quad .LBB0_4
.section ".note.GNU-stack","",@progbits
厚积薄发 穷且益坚
本帖最后由 oggplay 于 2014-6-25 14:29 编辑
给你个任务,检查一下C编译器为结构和联合的访问产生正确的代码,你写了下面的结构声明:typedef union {
struct {
shortv;
shortd;
int s;
} t1;
struct {
int a;
char*p;
} t2;
} 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。
这一小节比较生疏,但是又很重要,不得不分享一下。
数据对齐:
这是要探究一些底层的东西?还没仔细看。。。
本帖最后由 oggplay 于 2014-6-27 16:24 编辑
http://bbs.fishc.com/thread-48826-1-1.html 这是栈溢出的一个例子。以下是限制栈溢出的几种策略。
楼主加油!!!
越来越搞不懂了
祝坚持!厚积薄发~
过来看看啊 好东西