交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
4 操作数
分享
未结
0
829
李延
LV6
2022-06-01
悬赏:20积分
# 1 说明 大多数指令有一个或多个操作数(operand),指示出执行一个操作中要使用的源数据 值,以及放置结果的目的位置。 我们在前面的mov指令中也看到读取一个固定的数据 用`$`符号。而读取 寄存器是使用 `%`。 除了这两种方式外我们还可以读取内存数据。所有一个有3种不同的操作数类型 - 立即数:用来表 示常数值。在 ATT 格式的汇编代码中,立即数的书写方式是`$`后面跟一个整数,比如,`$-577 或$0xlF` - 寄存器: 它表示某个寄 存器的内容,16 个寄存器的低位 1 字节、2 字节、4 字节或 8 字节中的一个作为操作数, 这些字节数分别对应于 8 位、16 位、32 位或 64 位。通常使用 `%`加 寄存器名称表示 - 内存: 它会根据计算出来的地址(通常称为有效地址)访问某个内 存位置。因为将内存看成一个很大的字节数组,我们用符号 表示对存储在内存 中从地 开始的 6 个字节值的引用。为了简便,我们通常省去下标 6。 # 2 不同寻址方式 对于立即数与寄存器只有一种表示形式,而对于内存,有各自不同的寻址方式,我们逐一介绍, 并且通过mov操作进行说明 ## 2.1 直接寻址 ```asm movq (6422028), %rsi ``` 就是直接指定内存地址,将这个地址上的值 赋到rsi中。写法为 小括号 中间为具体的内存地址。 **注意** 在其他书籍中看用的是 中括号 `[]`表示, 但我自己测试的时候这样编译会报错,可能和我自己使用的环境有关系。 ## 2.2 间接寻址 ```asm movq (%rsp), %rsi ``` 寄存器的值是一个内存地址,将这个地址的内容加载到rsi中。测试用例: ```asm .LC0: .string "address %llu\n" .LC1: .string "value %ld\n" .globl main main: subq $8, %rsp movq $1, (%rsp) movl $.LC0, %edi movq %rsp, %rsi call printf movl $.LC1, %edi movq (%rsp), %rsi call printf movl $0, %eax addq $8, %rsp ret ``` 结果: ```shell [root@localhost addressing]# ./a.out address 140728605973248 value 1 ``` 我们看到直接打印寄存器的值是 140728605973248 ,它表示内存地址。而使用 (%rsp) 打印的是这个地址上的值,是1 ## 2.3 (基址 + 偏移量) 寻址 ```asm movq 1(%rsp), %rdx ``` 在间接寻址的基础上前面加一个数字。这个数字代表寻址的偏移量,单位是字节。比如:之前(%rsp)为 65523 那么:1(%rsp)就是 65524 示例: ```asm .LC0: .string "value1 %ld\n value2 %ld\n" .globl main main: subq $24, %rsp movq $0B111111111111, (%rsp) movl $.LC0, %edi movq (%rsp), %rsi movq 1(%rsp), %rdx call printf movl $0, %eax addq $24, %rsp ret ``` 结果: ```shell [root@localhost addressing]# ./a.out value1 4095 value2 15 ``` 我们这里将值rsp指向的内存设置为 0B111111111111 ,也就是在除了第一个字节外,上一个字节占用了 1111。我们设置的便宜1个字节,刚好取到的是高位的15。 ## 2.4 变址寻址 ```asm movq (%rsp,%rbx), %rsi ``` 通过两个寄存器,中间用逗号分隔,表示通过将两个寄存器的值相加后 进行寻址。 ```asm .LC0: .string "value %ld\n" .globl main main: subq $24, %rsp movq $123, 2(%rsp) movq $2, %rbx movl $.LC0, %edi movq (%rsp,%rbx), %rsi call printf movl $0, %eax addq $24, %rsp ret ``` 结果: ```shell [root@localhost addressing]# ./a.out value 123 ``` 我们设置%rbx寄存器为 2 ,也就是将其偏移量加2,进行寻址 ## 2.5 比例寻址 ```asm (寄存器,立即数) ``` 一个寄存器,一个立即数进行寻址,值为 寄存器 值乘以 立即数 值。 一般不会使用,而零一种是比较常用的 ```asm (寄存器A,寄存器B,立即数) ``` 寄存器A+寄存器B*立即数 这个比较常用,多用于数组的查找,一般情况下:寄存器A 是数组的首地址,寄存器B是数组单个元素的长度,立即数就是数组的下标 示例: ```asm .LC0: .string "value %ld\n" .globl main main: subq $24, %rsp movq $123, 4(%rsp) movq $2, %rbx movl $.LC0, %edi movq (%rsp,%rbx,2), %rsi call printf movl $0, %eax addq $24, %rsp ret ``` 结果: ```shell [root@localhost addressing]# ./a.out value 123 ```
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号