第六周IA-32指令类型

在线阅读PDF文档

指令内容比较繁琐,不需要记忆,只要求能看懂手册会用即可。下面使用的是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指令集共用同一套通用寄存器