《汇编语言程序设计》学习笔记(3)三、C与汇编语言

3.1 80x86汇编与C语言-1

3.1.1 80x86汇编与C语言-1 - 汇编程序员眼中的系统结构

汇编程序员眼中的系统结构

这里写图片描述

如何从C代码生成汇编代码

这里写图片描述

gcc -O2 -S code.c -m32 -fno-omit-frame-pointer

-O2 表示有一定的优化的 level ;
-S 表示要从 code.c 原始 c 程序,把它编译成一个.s汇编程序;
-m32 表示要生成32位代码。

汇编语言数据格式

这里写图片描述

3.1.2 80x86汇编与C语言-1 - 第一条汇编指令

第一条汇编指令实例

这里写图片描述

l 表示两个整数相加。

这条add指令操作数有两个 实际上就是x加y等于t因为是两个操作数 那么我们肯定知道就是说 肯定是8ebp eax相加 加起来之后的和放到eax里面去 也就是说这个指令的操作数是两个 目的寄存器是在右侧 那个 当然它既是目的又是源实际上 两个都是源 加完之后放到目的寄存器 目的寄存器就是右侧的第二个源 加起来就完了

数据传送指令(mov)

这里写图片描述

(
立即数,实际上就是常整数。
)

数据传送指令支持的不同操作数类型组合

这里写图片描述

括号里面是什么呢 表示内存地址。

(
例如 %eax ,表示内存地址。
)

简单的寻址模式

如果我们有个操作数是访问内存的话,那么内存地址怎么计算或者叫做怎么寻址?

这里写图片描述

(
- 间接寻址

movl (%ecx), %eax为例:

把寄存器 ecx 里面的数值作为内存地址去访问,把内存地址里面的数据拿出来,即,把内存地址所指明的那个位置里面的数据拿出来,把它作为操作数, moveax 寄存器。

备注:
1. 括号里面百分号 ecx (%ecx),表示地址;
2. 如果外面再有 1个常数,如果加上$ ,就表示它是 1 个常量,不是地址。

  • 基址+偏移量 寻址

movl 8(%ebp), %edx为例:

把寄存器ebp里面的值拿出来,加上 8 ,加出来的和作为内存的地址,有了内存地址后,把内存地址中的这个数取出来,取出来再挪过去。
)

  • 间接寻址

movl (%ecx),%eax中,(%ecx)就是把寄存器ecx里面的数值作为一个Memory的address,去访问Memory Address里面的数据,把这个数据拿出来,而不是Address拿出来,是把Memory Address所指明的那个位置里面的数据拿出来,把它作为操作数mov过去。这就叫做间接寻址。

  • 基址加偏移量的寻址

还有个叫做基址加偏移量的寻址 实际上跟那个差不多 无非就是说 我在括号外面加了一个常数 比方说这里面就是8 8括号百分号ebp 寄存器ebp里面的值拿出来加上8 加出来的和作为内存的地址 有了内存地址之后呢 把内存中的这个数取出来 取出来之后再挪过去 这个叫做基址加偏移量寻址

所以注意这种表示方式 括号里面百分号ecx 那么这样子的表示方式ecx value表示Address 如果外面再有一个常数 注意常数前面是没有dollar号 如果加上dollar号就是什么了 就表示它是一个常量不是地址 不要加这个 把两个数加起来之后变成内存地址 这就取出来 取出来的这个数就作为操作数之一挪过去

3.1.3 80x86汇编与C语言-1 - 寻址模式

寻址模式使用实例

swap.c:

void swap(int *xp, int *yp)
{
        int t0 = *xp;
        int t1 = *yp;
        *xp = t1;
        *yp = t0;
}

汇编得到的swap.s:

$ gcc -O2 -S swap.c -m32 -fno-omit-frame-pointer
$ cat swap.s
        .file   "swap.c"
        .section        .text.unlikely,"ax",@progbits
.LCOLDB0:
        .text
.LHOTB0:
        .p2align 4,,15
        .globl  swap
        .type   swap, @function
swap:
.LFB0:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        pushl   %ebx
        .cfi_offset 3, -12
        movl    8(%ebp), %edx
        movl    12(%ebp), %eax
        movl    (%edx), %ecx
        movl    (%eax), %ebx
        movl    %ebx, (%edx)
        movl    %ecx, (%eax)
        popl    %ebx
        .cfi_restore 3
        popl    %ebp
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
.LFE0:
        .size   swap, .-swap
        .section        .text.unlikely
.LCOLDE0:
        .text
.LHOTE0:
        .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
        .section        .note.GNU-stack,"",@progbits

这里写图片描述

实例分析

这里写图片描述

这里写图片描述

这里写图片描述

(
这一段视频对第一段汇编代码讲解非常详细,特别是每一条汇编指令,在栈中是怎么交换、移动、存放的,讲解的非常好。注意,上述的变换,建议看视频,比较详细,截图只放了 2 张。

建议先理解了数据结构中的栈,再来看这段视频,收获会非常大。
)

3.1.4 80x86汇编与C语言-1 - 地址计算指令与其它 - 1

变址寻址

这里写图片描述

寻址模式实例

这里写图片描述

这里写图片描述

地址计算指令

这里写图片描述

地址计算指令leal l表示后缀就是 我算的目的操作数是double word类型 那它实际上跟mov非常像 也是两个操作数 src和Destination 注意 src是地址计算表达式 什么叫做地址计算表达式 就像我们刚才说过了实际上就是变址寻址 一共四个要素 基址加上index乘上scale 再加上displacement 就是说src就是这种表达方式 只要是这种的合法表达方式 它就可以作为src

Destination一般来说就是个寄存器 就是说我把src的地址表达式值给算出来 算出来的地址赋给Destination

注意它跟mov很像 但是有本质上的不同 mov如果你的src是地址表达式的话 它会去访存 它把地址算出来之后 真真正正的去访存 访问Memory 把Memory中的数据取出来 再mov过去

leal很简单 我要算出的地址就是我所需要的数据 你把这个地址表达式写清楚 算完了 算完了之后这个地址本身 我是作为操作对象 挪到Destination里面去的 这是一个很大的区别 因为它是完成地址计算

所以说它的用途呢一大用途就是地址计算 但不访存 比方说在C里面我定义了数组x 一个什么什么的数组 我要计算它的地址 D等于一个取地址的运算x方括号i 这个很常见 屏幕上打出来的 这个很常见的 这种情况实际上就是用leal指令计算就完了 我还是把它的基址加上index 乘上sizeof就完了 对吧 这个算出来就是我所需要的地址 这个地址就是我的目标 我的目的 把这

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值