第六周IA-32指令类型
指令内容比较繁琐,不需要记忆,只要求能看懂手册会用即可。下面使用的是AT&T指令集,不是Intel80x86指令集。两者差异明显,比如mov指令是否加l,w等以及源操作数和目的操作数的位置不同。
第1讲 传送指令
1.常用传送指令(15分钟)
2.传送指令执行过程(5分钟)
还有一个问题就是因为虽说经常听到 PC 这个词,但是我却没有见到其实体,所以我的理解是 PC 实际上就是 CS:IP 组合的逻辑表示。PC 不是一个实体,真正用来表示 PC 值的是 CS:IP,所谓的 PC 自动增加是指令指针寄存器 IP 在自增?这个理解对吗?
在 x86 体系里是这样。x86 系统中自增的是 IP,用 CS:IP 组合表示正在执行的指令地址,此时 PC 只是一个概念上的说法。在 ARM 体系中 R15 就是 PC,当然 ARM 和 IA-32、x64 都支持高级内存管理,所以「PC」的内容未必是当前指令在内存中的绝对位置。
第2讲 定点算术运算指令
1.常用定点运算指令(9分钟)
定点算术运算指令汇总
2.加法运算的底层实现举例(15分钟)
#include <iostream>
#include <cstdio>
using namespace std;
int add(int i,int j)
{
int x = i + j;
return x;
}
int main()
{
int t1 = 2147483647;
int t2 = 2;
int sum = add(t1,t2);
printf("sum=%d",sum);
}
sum=-2147483647
ALU结构原理
3.加法指令和乘法指令举例(18分钟)
溢出标志OF:在运算过程中,如果操作数或结果超出了机器能表示的范围称为溢出。此时OF位置1,否则置0。简而言之,如果操作数符号相同,而结果与操作数符号不同,则发生了溢出。 上面是负数加负数还是负数,故没有溢出。
符号标志SF:计算运算结果的符号,若最高有效位为1则置为1,最高有效位为0则置为0
零标志ZF:计算结果为0时置为1,否则置为0
进位标志CF:CF=Cout XOR Sub。例如,执行加法指令时,最高有效位有进位时置1,否则置0。
第3讲 按位运算指令
1.逻辑运算和移位指令(12分钟)
2.按位运算指令举例(10分钟)
#include <stdio.h>
int main()
{
int a = 0x80000000;
unsigned int b = 0x80000000;
printf("0x%X\n",a>>1);
printf("0x%X\n",b>>1);
return 0;
}
0xC0000000
0x40000000
第4讲 控制转移指令
1.条件转移指令举例(22分钟)
#include <stdio.h>
int sum(int a[],unsigned len)
{
int i,sum = 0;
for(i=0;i<=len-1;i++)
sum += a[i];
return sum;
}
int main()
{
int a[4]={1,2,3,4};
unsigned int len = 0;
printf("%d\n",sum(a,len));
return 0;
}
Process returned -1073741819 (0xC0000005) execution time : 0.532 s
Press any key to continue.
这是个死循环。
#include <stdio.h>
int sum(int a[],int len)
{
int i,sum = 0;
for(i=0;i<=len-1;i++)
sum += a[i];
return sum;
}
int main()
{
int a[4]={1,2,3,4};
int len = 0;
printf("%d\n",sum(a,len));
return 0;
}
0
2.条件设置指令举例(5分钟)
#include <stdio.h>
int main()
{
unsigned int a = 1;
unsigned short b = 1;
char c = -1;
int d;
d = (a > c) ? 1 : 0;
printf("%d\n",d);
d = (a == c) ? 1 : 0;
printf("%d\n",d);
d = (b > c) ? 1 : 0;
printf("%d\n",d);
return 0;
}
a:0000 0000 0000 0000 0000 0000 0000 0001
b:0000 0000 0000 0001
c:1111 1111
0
0
1
第5讲 x87浮点处理指令
1. x87 FPU常用指令(11分钟)
2. x87浮点处理指令举例(15分钟)
#include <stdio.h>
int main()
{
int a = 10;
double *p = (double*)&a;
printf("%f\n",*p);
printf("%f\n",(double)a);
return 0;
}
0.000000
10.000000
老师说printf("%f\n",*p);
实际上会输出个不确定的值。
输出为%d格式会出现更玄乎的结果。
#include <stdio.h>
int main()
{
int a = 10;
double *p = (double*)&a;
printf("%d\n",*p);
printf("%d\n",(double)a);
return 0;
}
10
0
第6讲 MMX及SSE指令集
MMX及SSE指令集(14分钟)
第六周小测验
1单选(相对基址比例变址寻址方式)
某C语言程序中对数组变量b的声明为“int b[10][5];
”,有一条for语句如下:
for (i=0; i<10, i++)
for (j=0; j<5; j++)
sum+= b[i][j];
假设执行到“sum+= b[i][j];
”时,sum的值在EAX中,b[i][0]
所在的地址在EDX中,j在ESI中,则“sum+= b[i][j];
”所对应的指令(AT&T格式)可以是( A )。
A.addl 0(%edx, %esi, 4), %eax
B.addl 0(%esi, %edx, 4), %eax
C.addl 0(%edx, %esi, 2), %eax
D.addl 0(%esi, %edx, 2), %eax
2单选(popl指令)
IA-32中指令“popl %ebp”的功能是( D )。
A.R[esp]←R[esp]+4,R[ebp]←M[R[esp]]
B.R[esp]←R[esp]-4,R[ebp]←M[R[esp]]
C.R[ebp]←M[R[esp]],R[esp]←R[esp]-4
D.R[ebp]←M[R[esp]],R[esp]←R[esp]+4
3单选(movl指令)
IA-32中指令“movl 8(%edx, %esi, 4), %edx
”的功能是( D )。
A.M[R[esi]+R[edx]*4+8]←R[edx]
B.R[edx]←M[R[esi]+R[edx]*4+8]
C.M[R[edx]+R[esi]*4+8]←R[edx]
D.R[edx]←M[R[edx]+R[esi]*4+8]
4单选(movswl指令)
设SignExt[x]
表示对x符号扩展,ZeroExt[x]
表示对x零扩展。IA-32中指令“movswl %cx, -20(%ebp)
”的功能是( D )。
A.M[R[ebp]-20]←ZeroExt[R[cx]]
B.R[cx]←ZeroExt [M[R[ebp]-20]]
C.R[cx]←SignExt [M[R[ebp]-20]]
D.M[R[ebp]-20]←SignExt[R[cx]]
5单选(subw指令)
假设 R[ax]=FFE8H,R[bx]=7FE6H
,执行指令“subw %bx, %ax
”后,寄存器的内容和各标志的变化为( A )。
A.R[ax]=8002H
,OF=0,SF=1,CF=0,ZF=0
B.R[bx]=8002H
,OF=1,SF=1,CF=0,ZF=0
C.R[ax]=8002H
,OF=1,SF=1,CF=0,ZF=0
D.R[bx]=8002H
,OF=0,SF=1,CF=0,ZF=0
解析: A、指令在补码加减运算部件中执行:1111 1111 1110 1000+1000 0000 0001 1001+1 =(1)1000 0000 0000 0010(8002H),结果无溢出(OF=0)、负数(SF=1)、没有借位(CF= (1 异或 1) =0)、非0(ZF=0)。
6单选(imulw指令)
假设R[eax]=0000B160H,R[ebx]=00FF0110H
,执行指令“imulw %bx
”后,通用寄存器的内容变化为( D )。
A.R[eax]=FFAC7600H
,其余不变
B. R[eax]=00BC7600
,其余不变
C.R[eax]=00007600H,R[dx]=00BCH
D.R[eax]=00007600H,R[dx]=FFACH
解析: D、因为一个源操作数为BX寄存器中的内容,所以只要将AX和BX中的内容相乘即可。指令在带符号乘法部件中执行,B160H*0110H=FFFB1600+FFB16000=FFAC7600H
,DX寄存器内容为FFACH,AX寄存器内容为7600H,EAX中高16位不变。
7单选(salw指令)
假设short型变量x被分配在寄存器AX中,若R[ax]=FF70H
,则执行指令“salw $2, %ax
”后,变量x的机器数和真值分别是( C )。
A.3FDC,16348
B. FFDCH,-36
C.FDC0H,-576
D.FDC3H,-573
解析: C、salw指令是算术左移指令,对FF70=1111 1111 0111 0000算术左移2位后,结果为1111 1101 1100 0000(FDC0H),真值为-10 0100 0000B = -(512+64) = -576。
8单选(cmpl比较指令和jle转移指令)(难点)
程序P中有两个变量i和j,被分别分配在寄存器EAX和EDX中,P中语句“if (i<j) { …}”对应的指令序列如下(左边为指令地址,中间为机器代码,右边为汇编指令):
804846a 39 c2 cmpl %eax, %edx
804846c 7e 0d jle xxxxxxxx
若执行到804846a处的cmpl指令时,i=105,j=100,则jle指令执行后将会转到( A )处的指令执行。
A.804847b
B.8048479
C.804846e
D.8048461
解析: A、因为cmpl指令中EDX内容为100,EAX内容为105,对这两个数做减法,显然100<105,满足jle指令小于或等于的条件,执行完jle指令后将转移到PC+偏移量=0x84846c+2+0d=0x804847b去执行。
9单选(x87 FPU浮点处理指令系统)
以下关于x87 FPU浮点处理指令系统的叙述中,错误的是( A )。
A.float和double型数据从主存装入浮点寄存器时有可能发生舍入,造成精度损失
B.提供8个80位浮点寄存器ST(0)~ST(7),采用栈结构,栈顶为ST(0)
C. float、double和long double型数据存入主存时,分别占32位、64位和96位
D.float、double和long double三种类型数据都按80位格式存放在浮点寄存器中
10单选(MMX/SSE指令集)
以下关于MMX/SSE指令集的叙述中,错误的是( D )。
A. SSE指令是一种采用SIMD(单指令多数据)技术的数据级并行指令
B. 同一个微处理器同时支持IA-32指令集与MMX/SSE指令集
C. 目前SSE支持128位整数运算或同时并行处理两个64位双精度浮点数
D. MMX/SSE指令集和IA-32指令集共用同一套通用寄存器