Machine Prog.

IA32, IA64, x86 (a.k.a x86-64), AMD, ARM这些处理器的指令集向上为汇编语言提供了接口,可以把汇编语言看成高阶API,然后让硬件工程师去实现,该课程是按照x86-64指令集为标准做介绍的,所以由于历史遗留原因,64位的处理器的registers有很多奇怪的名字,这很大原因是因为很久以前比如386,8086等时期设计了一些“特殊意义”的registers,但是先进大多数已经不再单独规范它们的功能了,所以名字就留下来了,这点和我们编程一个道理,很久前的代码命的名字就不用改了嘛,为了兼容性的考虑,但是有一个registers叫做 %rbpbase pointer 这个要特别注意,同时再记住两个特殊的registers: %rdi 以及 %rsi ,这两个分别代表函数的前两个”参数”.

Register中的数据可以被移动到指定内存中,同时也可以将内容移动到另外的register中,其实register可以看成是一个变量,而”指定内存“可以看成一个指针变量,比如: (提醒,这里的movq,q是(quadword四字)的简称,是64位中,一次性移动64位,4个字节的位置)

int a = b;    movq %rdi %rax   // 这里b是%rdi, a是%rax;
int *b;
b = a;        movq %rdi (%rax) // 将register %rdi中的内容放入内存中,内存地址这里用括号()括起来,表示register %rax是一个内存地址

还可以常量直接移动到register中,也可以直接放在内存中:

int a = 0x1;  movq 0x1 %rdi    // 常量直接复制给register
int *p;
*p = 0x1;     movq 0x1 (%rax)

也可以将内存地址中的 内容 (如果想拿到内存地址的话要用leaq,后面会说到)放入register中:

int *a;
int b;

b = *a;       movq (%rax)  %rdi;

内存中的 内容 也可以从地址1变到内存中的地址2,但是因为硬件设计的原因,这一操作没法直接进行,所以就只能先从内存移动到register,然后再从register移动到内存中:

int *a;
int *b;

int c;

c = *a;     movq (%rax) %rdi
*b = c;     movq %rdi   (%rsi)

因为是64位的,所以移动默认是4bytes,如果要对读取的地址进行移位,可以通过:比如:8(%rdx)就是从 %rdx中存的内存地址+8 ,当然这只是移位的一种表示方法,下面会介绍更多。

比如:%rdx = 0xf000,%rcx = 0x0100;

如下表达式的对应关系分别是:

0x8(%rdx)  -> 0xf000 + 0x8 = 0xf008
(%rdx, %rcx) -> 0xf000 + 0x0100 = 0xf100;
(%rdx, %rcx, 4) -> 0xf00 + 0x0100 * 4 = 0xf400;
0x80( , %rdx, 2) -> 0xf000*2 + 0x80                 //就是最后一个比如这个2和上面的4,乘以倒数第二个,加上最前面的,不用管逗号
0x80(%rdx, %rcx) -> %rcx + %rdx + 0x80            //如果没有scale index (s),那么前面就直接相加
我来评几句
登录后评论

已发表评论数()