csappchap3(2)

本文介绍了C语言中ifelse、循环(do-while、while、for和switch-case)、以及数组指针和结构的汇编对应,强调了条件传送中使用goto/jmp的技巧,并讨论了如何通过优化避免不必要的开销,如时间消耗和内存对齐问题。

接着来实现C语言常用语法底层:

if else语句

条件控制
if(test_expr){
	then_expr;
}else{
	else_expr;
}

写成更像汇编的C语言版本:

if(!test_expr){
	goto ELSE;
}
THEN:then_expr
goto DONE
ELSE:else_expr
DONE:
...

将goto 换成对应的jmp语句即是相关的汇编代码

条件传送

两个分支的值都计算出来,再根据判断条件将正确的结果赋给它,一般能节省时间

//不适合的例子
int t = p ? (*p) : 0; //解引用空指针
int t = condition ? Hard_exp1 : Hard_exp2; //时间开销反而更大
int t = x > 0? x *= 3 : x += 5;  //使得传送结果变化

循环

do-while
LOOP:
	body
if(test_expr) goto LOOP;

while
//两种实现
//1.jump to middle(-Og)
goto TEST;
LOOP:
	body
TEST:
	if(test_expr) goto LOOP;
//2.guarded-do(-O1)
//先测试初始条件是否满足,满足就转化为do-while实现,否则跳出
t = test_expr;
if(!t) goto DONE;
do
	body
while(test_expr);
DONE:

for循环

比while多一个初始块和更新块,略

switch-case

  1. 跳转表
    表的内容是地址,对应某一case所需执行代码的首地址
    跳转表本身是连续的,方便索引
    索引方式为:
jmp * .Label( , %rdi, 8) // switch对象为long类型

// jmp 默认跟地址, 加上* 表示从后面的内容里取得地址
// jmp %rax 不允许, 而 jmp * %rax允许
//与内存寻址有点不同
  1. 规则
    首先将索引值偏移到0附近(加减某一值),大于某一阈值的直接落入default
    在正确区间内,但没有指定操作的也在default块里
    由于跳转表指向的内容往往连续,所以在没有break的情况下会继续执行下一个case

数组 指针 结构(struct)

  1. 多维数组与多级数组
    多维数组
    多个行向量组合而成
    在不同行向量间跳转的地址可以计算
    每一个行向量就是一个普通的一维数组
    多级数组
    上一级的数组是存放指向下一级数组首地址的指针
    对应的C代码很像,但地址计算不一样
  2. 指针(略)
  3. 结构(看成 可以存放不同类型 的数组)
    访问结构体的成员是 编译器做内存地址的偏移,从而得到正确的结果
    往往需要内存对齐
    内存对齐
    如果一个基本数据类型占用K字节,那么它的偏移量也应该是K的倍数
    基地址和总大小也必须是K的倍数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

雾影林深

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

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

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

打赏作者

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

抵扣说明:

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

余额充值