第四章 数据传送,寻址和算术运算
4.1 数据传送指令
4.1.2 操作数类型
操作数有 3 种基本类型:
- 立即数——用数字文本表达式
- 寄存器操作数——使用 CPU 内已命名的寄存器
- 内存操作数——引用内存位置
操作数 | 说明 |
---|---|
reg8 | 8 位通用寄存器:AH、AL、BH、BL、CH、CL、DH、DL |
reg16 | 16 位通用寄存器:AX、BX、CX、DX、SI、DI、SP、BP |
reg32 | 32 位通用寄存器:EAX、EEX、ECX、EDX、ESI、EDI、ESP、EBP |
reg | 通用寄存器 |
sreg | 16 位段寄存器:CS、DS、SS、ES、FS、GS |
imm | 8 位、16 位或 32 位立即数 |
imm8 | 8 位立即数,字节型数值 |
imm16 | 16 位立即数,字类型数值 |
imm32 | 32 位立即数,双字型数值 |
reg/mem8 | 8 位操作数,可以是 8 位通用寄存器或内存字节 |
reg/mem16 | 16 位立即数,可以是 16 位通用寄存器或内存字 |
reg/mem32 | 32 位立即数,可以是 32 位通用寄存器或内存双字 |
mem | 8位、16 位或 32 位内存操作数 |
直接内存操作数:变量名引用的是数据段内的偏移量。
4.2 加法和减法
4.2.4 NEG指令
NEG:通过将数字转换为对应的补码而求得其相反数。
TITLE Add and Subtract INCLUDE Irvine32.inc ;计算26+(-25) .data Val SDWORD 25 .code main PROC mov eax,Val neg eax;-25 add eax,26 call DumpRegs INVOKE ExitProcess,0 main ENDP END main
4.3 和数据相关的操作符和伪指令
OFFSET 运算符返回数据标号的偏移量。这个偏移量按字节计算,表示的是该数据标号距离数据段起始地址的距离。
TITLE test INCLUDE Irvine32.inc .data Val SDWORD 25 Val1 SDWORD 66 .code main PROC mov esi,OFFSET Val mov edi,OFFSET Val1 mov eax,0 mov eax,[esi] call DumpRegs INVOKE ExitProcess,0 main ENDP END main
ALIGN 伪指令将一个变量对齐到字节边界、字边界、双字边界或段落边界。
bVal BYTE ? ;00404000h ALIGN 2 wVal WORD ? ;00404002h bVal2 BYTE ? ;00404004h ALIGN 4 dVal DWORD ? ;00404008h dVal2 DWORD ? ;0040400Ch
PTR 运算符可以用来重写一个已经被声明过的操作数的大小类型。
TITLE test INCLUDE Irvine32.inc .data Val SDWORD 12345678h .code main PROC mov eax,0 mov ax,WORD PTR Val;ax=5678h call DumpRegs INVOKE ExitProcess,0 main ENDP END main
TYPE 运算符返回变量单个元素的大小,这个大小是以字节为单位计算的。比如,TYPE 为字节,返回值是 1;TYPE 为字,返回值是 2;TYPE 为双字,返回值是 4;TYPE 为四字,返回值是 8。
LENGTHOF 运算符计算数组中元素的个数,元素个数是由数组标号同一行出现的数值来定义的。
LABEL 伪指令可以插入一个标号,并定义它的大小属性,但是不为这个标号分配存储空间。
.data val16 LABEL WORD val32 DWORD 12345678h .code mov ax,val16 ; AX = 5678h mov dx,[val16+2] ; DX = 1234h
4.4 间接寻址
4.4.1间接操作数
保护模式
任何一个 32 位通用寄存器(EAX、EBX、ECX、EDX、ESI、EDI、EBP 和 ESP)加上括号就能构成一个间接操作数。
变址操作数
变址操作数是指,在寄存器上加上常数产生一个有效地址。每个 32 位通用寄存器都可以用作变址寄存器。MASM 可以用不同的符号来表示变址操作数(括号是表示符号的一部分):
使用 16 位寄存器
在实地址模式中,一般用 16 位寄存器作为变址操作数。在这种情况下,能被使用的寄存器只有 SI、DI、BX 和 BP:
变址操作数中的比例因子
在计算偏移量时,变址操作数必须考虑每个数组元素的大小。比如下例中的双字数组,下标(3 )要乘以 4(一个双字的大小)才能生成内容为 400h 的数组元素的偏移量
4.4.4 指针
TITLE test program INCLUDE Irvine32.inc ;创建用户自定义类型 PBYTE TYPEDEF PTR BYTE PWORD TYPEDEF PTR WORD PDWORD TYPEDEF PTR DWORD .data Str1 BYTE 1,2,3 Str2 WORD 4,5,6 Str3 DWORD 7,8,9 ;创建指针变量 ptr1 PBYTE Str1 ptr2 PWORD Str2 ptr3 PDWORD str3 .code main PROC mov esi,ptr1;将指针变量的值赋值 mov eax,0 mov al,[esi + TYPE Str1] mov eax,0 mov esi,ptr2 mov ax,[esi + TYPE Str2] mov eax,0 mov esi,ptr3 mov eax,[esi + TYPE Str3] call DumpRegs exit main ENDP END main
4.7 编程练习
1.
Title Test Project INCLUDE Irvine32.inc .code main PROC mov eax,0 ;mov不影响标志寄存器 mov ax,0FFFFh call DumpRegs ;add影响标志寄存器,且进位了(ax无法容纳10000h) add ax,2 call DumpRegs ;sub影响标志寄存器,但未产生进位1-1=0000h sub ax,1 call DumpRegs exit main ENDP END main
2.
Title Test Project INCLUDE Irvine32.inc .code main PROC mov eax,0 mov ax,0FFFFh call DumpRegs inc ax call DumpRegs inc ax call DumpRegs dec ax call DumpRegs dec ax call DumpRegs exit main ENDP END main
3.
Title Test Project INCLUDE Irvine32.inc .code main PROC mov eax,0 ;变成-1,影响符号位 add ax,-1 call DumpRegs ;变成0,影响符号位 add ax,1 call DumpRegs exit main ENDP END main
4.
Title Test Project INCLUDE Irvine32.inc .code main PROC mov eax,0 ;变成-1,影响符号位 add ax,-1 call DumpRegs ;变成0,影响符号位 add ax,1 call DumpRegs exit main ENDP END main
5.
Title Test Project INCLUDE Irvine32.inc .data Uarray WORD 1000h,2000h,3000h,4000h Sarray SWORD -1,-2,-3,-4 .code main PROC mov eax,0 mov ebx,0 mov ecx,0 mov edx,0 movzx eax, Uarray movzx ebx, Uarray+2 movzx ecx, Uarray+4 movzx edx, Uarray+6 call DumpRegs mov eax,0 mov ebx,0 mov ecx,0 mov edx,0 movsx eax, Sarray movsx ebx, Sarray+2 movsx ecx, Sarray+4 movsx edx, Sarray+6 call DumpRegs exit main ENDP END main
6.
TITLE TEST PROJECT INCLUDE Irvine32.inc .data NUM1 DWORD 1 NUM2 DWORD 1 .code main PROC mov eax,0 mov ebx,0 mov edx,0 mov ecx,0 add eax,NUM1 add eax,NUM2 mov edx,NUM2;将edx作为当前的最大值 mov ecx,10 S: mov ebx,NUM1 mov NUM1,edx;最大值更新之后,NUM1将变成原最大值 add edx,ebx;最大值edx更新 add eax,edx;和更新 LOOP S call DumpRegs exit main ENDP END main
7.
TITLE TEST PROJECT INCLUDE Irvine32.inc .data val1 SDWORD 8 val2 SDWORD -15 val3 SDWORD 20 .code main PROC mov eax,val2;eax=FFFF FFF1H NEG eax;eax=0000 0000FH add eax,7;eax=0000 0016H sub eax,val3;eax=0000 0002H add eax,val1;eax=0000 000AH call DumpRegs exit main ENDP END main
8.
TITLE TEST PROJECT INCLUDE Irvine32.inc .data source BYTE "This is the source string",0 target BYTE SIZEOF source DUP('#') .code main PROC mov eax,0 mov esi,0 mov edi,SIZEOF source - 1;不能包含0,大小-1 dec edi;末尾元素坐标,[size - 1] mov ecx,SIZEOF source - 1;大小-1 S: mov al,source[esi] mov target[edi],al inc esi dec edi loop S mov esi,OFFSET target mov ebx,1 mov ecx,SIZEOF target - 1 call DumpMem exit main ENDP END main