第三章
3.1简答题
🥚(1)使用二进制8位表达无符号整数,257有对应的编码吗?
答:没有,11111111=255为最大的二进制8位表达的无符号整数。(p60)
🥚(2)字符“F"和数值46H作为MOV指令的源操作数有区别吗?
答:字符“ 'F'”的 ASCII 码就是数值 46H,所以没有区别。(p72)
🥚(3)为什么可以吧指令'MOV AX ,(34+67H)*3'中的数值表达式看成是常量。
答:汇编程序在汇编过程中对数值表达式计算,得到一个确定的数值,故称数值表达式为常量。(p65)
⛔️ 注意:该寻址方式为立即数寻址。
🥚(4)数值500能够作为字节变量的初值吗?
答:不能,字节变量最大能够存储的数值为无符号数位0-255,有符号数位-128~127.所以不能为字节变量赋值。(p66)
🥚(5)为什么说“XCHG EDX ,CX”是一条错误指令?
答:源、目标寄存器位数不同,不能用该指令进行数据交换。(p72)
🥚(6)都是获取偏移地址,为什么指令“LEA EBX ,[ESI]"正确,而指令”,MOV EBX,OFFSET [ESI]"就错误?
答:前者在指令执行时获得偏移地址, 是正确的;但后者的 OFFSET只能在汇编阶段获得偏移地址, 但此时寄存器内容是不可知的,所以无法获得偏移地址。(p78)
⛔️ 注意:LEA:获取有效地址指令。
🥚(7)INC,EDC,NEG和NOT都是单操作数指令,这个操作数应该是源操作数还是目的操作数。
答:即是目的操作数也是源操作数。(P82)
⛔️ 注意:
-
INC:增量指令。INC reg/men ;reg/men=reg/men+1.设计增量指令的目的,主要是针对计数器和地址指针进行调整,所以它不影响进位CF标志,但影响其他状态标志位。
-
EDC:减量指令。
-
NEG:求补指令。NEG reg/men ;reg/men=0- reg/men.
-
NOT:逻辑非指令。
🥚(8)大小写字母转换利用了什么规律?
答: 大小写字母转换利用它们的 ASCII 码相差 20H。(p89)
⛔️ 注意:大写字母“A”的ASCII码值为41H(01000001B),D5=0.而小写字母“a”的ASCII码值为61H(01100001B)D5=1.和数据”00100000B“相异或则改变字母大小写。
🥚(9)乘除法运算针对无符号数和有符号数有两种不同的指令,只有一种指令的加减法如何区别无符号数和有符号数运算?
答:加减法不区别无符号数和有符号数, 但根据运算结果分别设置标志寄存器的 CF 和 OF 标志,可 利用 CF 和 OF 进行区别。(p79)
🥚(10)逻辑与运算为什么也称为逻辑乘?
答: 逻辑与运算规则类似二进制的乘法,所以称其为逻辑乘。(p87)
3.2判断题
🎅 (1)对一个正整数,它的源码、反码、和补码都一样,也都与无符号数的编码一样。✔️
解释:(p61)
🎅 (2)常用的BCD码为8421BCD码,其中8表示D3位的权重。✔️
解释:8421 BCD码,其中8 4 2 1 分别为D3 D2 D1 D0位的权重。
🎅 (3)IA-32处理器采用的是小端方式存储多字节数据。✔️
解释:(p68)"低对低,高对高“称为小端方式。
🎅 (4)空操作NOP指令其实根本没有指令。❌
解释:有时利用NOP指令实现短时间延时,还可以临时占用代码空间以便后续填入需要的指令代码。(p73)
🎅 (5)堆栈的操作原则的“先进后出”,所有堆栈端的数据除PUSH和POP指令外,不允许使用其他方法读写。❌
解释:除堆栈操作指令外,子程序调用CALL和子程序返回RET,中断调用INT,和中断返回IRET等指令,以及内部异常,外部中断等情况都会使用堆栈,修改ESP值。(p76)
🎅 (6)虽然ADD指令和SUB指令执行后会影响标志状态,但执行前的标志并不影响他们的执行结果。✔️
解释:ADD加法指令,SUB减法指令。标志状态是加减运算,逻辑运算等指令的辅助结果。(p79)
🎅 (7)指令INC ECX和ADD ECX,1 的实现功能完全一样,可以相互替换。❌
解释:INC不会影响CF标志位,但影响其他标志位,而ADD按照定义影响六个标志位。(p81)
🎅 (8)无符号数在前面加零扩展,数值不变;有符号数前面的进行符号扩展,位数加长一位,数值增加一倍。❌
解释:零位扩展对应无符号数,MOVZX,符号扩展对应有符号数,MOVSX,他们使数据位数加长,但数据大小并没有发生改变。(P86)
MOV AL,82H
MOVSX BX,AL ;AL=82H,符号扩展:BX=FF82H
🎅 (9)逻辑运算没有进位或溢出问题,此时CF和OF没有作用,所以逻辑运算指令(如:AND,OR等)将CF和OF设置为0✔️
解释:(p87)
🎅 (10)CMP指令是目的操作数减去源操作数,CMPS指令是源操作数减去目的操作数✔️
解释:CMP比较指令,只相减,不保存,对状态标志位产生影响。cmps:串比较指令(p83,p94)
3.3填空题
🎯 (1)定义字节变量的伪指令助记符是byte,获取变量名所具有的偏移地址的的操作符是offset
解释:(p66,p70)
🎯 (2)计算机中有一个’01100001‘编码。如果认为他是无符号数他是十进制数97;如果认为他是BCD码,则表示真值61,如果他是某个ASCII码,则代表字符a。
解释:01100001=61h=97d,(p62)
🎯 (3)C语言中用“\n”表示让光标回到下一行首位,在汇编语言中需要输出两个控制字符,一个是回车,其ASClI码为0DH,它将光标移动到当前所在行首位,另一个是换行,其ASCII码为0AH,它将光标移到下一行。
解释:p62
🎯 (4)数据段有语句“H8843 DWORD 99008843H",代码段指令”MOV CX,WORD PTR H8843“执行后CX=8843H.
解释:(p69)
🎯 (5)用DWORD定义一个变量XYZ,它的类型为DWOED,用“type xyz"后会得到数值为4,如果可以将其以字量使用,应该用WORD PTR XYZ说明。
解释:DWORD表示双字,32位数据,占4个字节,(p69,p71)
🎯 (6)数据段有语句"ABC BYTE 1,2,3",代码段指令'MOV CL,ABC+2'执行后cl=3
解释:直接地址。相当于数组,(p50)
🎯 (7)例3-9的TAB定义如果是“1234567890”则显示结果为78894111
解释:AL=6时,ebx=1,则XLAT 执行后;AL=AL+EBX=7,
同理7+1=8,8+1=9,3+1=4,0+1=1(p77)
🎯 (8)指令“XOR EAX,EAX"和”SUB EAX,EAX"执行后,EAX=0,CF=OD=0.而指令"MOV EAX,0"执行后,EAX=0,CF和OF没有变化。
解释:XOR:逻辑异或指令。“XOR EAX,EAX“执行后EAX=0.CF=OF=0,所以SUB EAX,EAX"执行后EAX=0,CF=OD=0.直接传输0进入寄存器也可以清零,但状态标志没有被改变(p89),
🎯 (9)例3-15的程序执行结束后,变量QVAR的内容是0123456788765432H,BCD的内容是83H
解释:
-
loop循环指令,ECX为计数器,每执行一次ECX=ECX-1.(p113)
-
SHR:l逻辑右移。(p90)
-
RCR:带进位右循环移位(p91)
🎯 (10)欲将EDX内的无符号整数除以16,使用指令“SHR EDX ,4",其中后一个操作数是一个立即数。
解释:shr指令执行一次逻辑右移位,相当于除以二,余数由CF标志保存(p91)
3.4下列十六进制数表示无符号整数,请转换为十进制形式的真值: ① FFH ② 0H ③ 5EH ④ EFH
答:AN
FFH=15*16+15=255D
.0H=0D
5EH=5*16+14=94D
EFH=14*16+15=239D
3.5将下列十进制数真值转换为压缩 BCD 码: ① 12 ② 24 ③ 68 ④ 99 (p62)
答:
0001 0010=12H
0010 0100=24H
0110 1000=68H
1001 1001=99H
🚫 注意:一个字节表达两个BCD码,称为压缩BCD码。
3.6将下列压缩 BCD 码转换为十进制数: ① 10010001 ② 10001001 ③ 00110110 ④ 10010000(P62)
答:
1001 0001=91D
1000 1001=89D
0011 0110=36D
1001 0000=90D
🚫 注意:BCD码虽然浪费了6个编码,但是能够直观的表达十进制数。
3.7将下列十进制数用 8 位二进制补码表示: ① 0 ② 127 ③-127 ④ -57(P61)
答:
[0]补=0000 0000
[127]补=0111 1111
[-124]补=1000 0001
[-57]补=1100 0111
🚫 注意:补码运算方式:
正数的原码和反码与补码和无符号数一样。负数的原码是对应正数原码符号位改为一,负数的反码是对应正数反码的取反。补码是负数反码加一。
3.8进行十六进制数据的加减运算,并说明是否有进位或借位: ① 1234H+7802H ② F034H+5AB0H ③ C051H-1234H ④ 9876H-ABCDH (p58)
答:
1234H+7802H=8A36H,无进位
F034H+5AB0H=4AF4H,有进位
C051H-1234H=BE1DH,无借位
9876H-ABCDH=ECA9H,有借位
🚫 注意:二进制算数运算:
3.9数码 0~9、大写字母 A~Z、小写字母 a~ z 对应的 ASCII 码分别是多少? ASCII 码 0DH 和 0AH 分别对应什么字符?(p63)
答:
-
数码 0~9 对应的 ASCII 码依次是 30H~39H。
-
大写字母 A~Z 对应的 ASCII 码依次是: 41H~5AH。
-
小写字母 a~z对应的 ASCII 码依次是: 61H~7AH。
-
ASCII 码 0DH 和 0AH 分别对应的是回车和换行字符。
3.10设置一个数据段,按照如下要求定义变量或符号常量:
① my1b为字符串变量: Personal Computer
② my2b为用十进制数表示的字节变量: 20
③ my3b为用十六进制数表示的字节变量: 20
④ my4b为用二进制数表示的字节变量: 20
⑤ my5w 为 20 个未赋值的字变量
⑥ my6c 为 100 的常量
⑦ my7c 表示字符串: Personal Computer
(p66)
答:
my1b byte "Personal Computer"
my2b byte 20
MY3B BYTE 14H
MY4B BYTE 00010100B
MY5W WORD 20 DUP(?)
MY6C = 100
MY7C EQU < Personal Computer >
🚫注意:
dup即英文duplicate的缩写,重复的意思,用来定义重复的字节、字、双字、结构等内存缓冲区。
它可以按照给定的次数来复制某个操作数,可以避免多次输入同样一个数据。
其中:
符号名 equ 数值表达式
符号名 equ <字符串>
符号名 = 数值表达式
db x dup () ;x是重复的次数,()里是要重复的数逗号分隔。
3.11 定义常量 NUM ,其值为 5;数据段中定义字数组变量 DATALIST,它的头 5 个字单元中依次存放 -10,2,5 和 4,最后 1 个单元初值不定。(P66)
答:
num = 5
DATALIST BYTE -10,2,5,4,?
3.12从低地址开始以字节为单位,用十六进制形式给出下列语句依次分配的数值: (P68)
byte 'ABC',10,10h,'EF',3 dup(-1,?,3 dup(4))
word 10h,-5,3 dup(?)
答:
41 42 43 0A 10 45 46 FF 00 04 04 04 FF 00 04 04 04 FF 00 04 04 04
10 00 FB FF 00 00 00 00 00 00
🚫注意:低地址开始以字节为单位,所有第二条语句的地址排放为.所有写出分配为10 00 FB FF
FF | 高地址 |
---|---|
FB | |
00 | |
10 | 低地址 |
3.13设在某个程序中有如下片段,请写出每条传送指令执行后寄存器 EAX 的内容: (p72)
; 数据段 org 100h varw word 1234h,5678h varb byte 3,4 vard dword 12345678h buff byte 10 dup(?) mess byte 'hello' ; 代码段 mov eax,offset mess mov eax,type buff+type mess+type vard mov eax,sizeof varw+sizeof buff+sizeof mess mov eax,lengthof varw+lengthof vard
答:执行后EAX内容为:
mov eax,offset mess ;EAX=100h+4+2+4+10=0114H mov eax,type buff+type mess+type vard ;EAX=1+1+4=0006H mov eax,sizeof varw+sizeof buff+sizeof mess ;EAX=4+10+5=0013H mov eax,lengthof varw+lengthof vard ;EAX=2+1=0003H
🚫注意:
-
TYPE:后跟变量返回该类型变量的一个数据项所占的字节数,后跟常量或寄存器名,分别返回0和该寄存器具有的字节数。
-
SIZEOF:获取变量所占用的字节空间
-
LENGTHOF:获知某变量指向多少个数据项。SIZEOF=LENGTHOF*TYPE
3.14按照如下输出格式,在屏幕上显示 ASCII 表:
| 0 1 2 3 4 5 6 7 8 9 A B C D E F ---+-------------------------------- 20 | ! “ # ... 30 | 0 1 2 3 ... 40 | @ A B C ... 50 | P Q R S ... 60 | ‘ a b c ... 70 | p q r s ...
表格最上一行的数字是对应列 ASCII 代码值的低 4 位(用十六进制形式) ,而表格左边的数字对应 行 ASCII 代码值的高 4 位(用十六进制形式)。编程在数据段直接构造这样的表格、 填写相应 ASCII 代码值(不是字符本身) ,然后使用字符串显示子程序 DISPMSG 实现显示。
答:
include io32.inc .data;代码段 table byte ' | 0 1 2 3 4 5 6 7 8 9 A B C D E F',13,10 byte '---+-------------------------------',13,10 byte '20 |',20h,20h,21h,20h,22h,20h,23h,20h,24h,20h,25h,20h,26h,20h,27h,20h,28h,20h,29h,20h byte 2ah,20h,2bh,20h,2ch,20h,2dh,20h,2eh,20h,2fh,20h,13,10 byte '30 |',30h,20h,31h,20h,32h,20h,33h,20h,34h,20h,35h,20h,36h,20h,37h,20h,38h,20h,39h,20h byte 3ah,20h,3bh,20h,3ch,20h,3dh,20h,3eh,20h,3fh,20h,13,10 byte '40 |',40h,20h,41h,20h,42h,20h,43h,20h,44h,20h,45h,20h,46h,20h,47h,20h,48h,20h,49h,20h byte 4ah,20h,4bh,20h,4ch,20h,4dh,20h,4eh,20h,4fh,20h,13,10 byte '50 |',50h,20h,51h,20h,52h,20h,53h,20h,54h,20h,55h,20h,56h,20h,57h,20h,58h,20h,59h,20h byte 5ah,20h,5bh,20h,5ch,20h,5dh,20h,5eh,20h,5fh,20h,13,10 byte '60 |',60h,20h,61h,20h,62h,20h,63h,20h,64h,20h,65h,20h,66h,20h,67h,20h,68h,20h,69h,20h byte 6ah,20h,6bh,20h,6ch,20h,6dh,20h,6eh,20h,6fh,20h,13,10 byte '70 |',70h,20h,71h,20h,72h,20h,73h,20h,74h,20h,75h,20h,76h,20h,77h,20h,78h,20h,79h,20h byte 7ah,20h,7bh,20h,7ch,20h,7dh,20h,7eh,20h,7fh,20h,13,10 byte 0 .code ;代码段 start: mov eax,offset table call dismsg exit 0 end atart
🚫注意:
3.15数据段有如下定义, IA-32 处理器将以小端方式保存在主存: var dword 12345678h 现以字节为单位按地址从低到高的顺序,写出这个变量内容。并说明如下指令的执行结果: mov eax,var ; EAX=__ mov bx,var ; BX=__ mov cx,var+2 ; CX=__ mov dl,var ; DL=__ mov dh,var+3 ; DH=__ 可以编程使用十六进制字节显示子程序 DSIPHB 顺序显示各个字节进行验证,还可以使用十六进 制双字显示子程序 DSIPHD 显示该数据进行对比。(p69)
答:小端方式采用“低对低、高对高” ,即低字节数据存放在低地址存储单元、高字节数据存放在高地 址存储单元。以字节为单位按地址从低到高的顺序, var 变量的内容: 78H、56H、34H、12H。
.data ;数据段 var dword 12345678h .code ;代码段 mov eax,var ; EAX=_12345678H__ mov bx,var ; BX=_5678H_________ mov cx,var+2 ; CX=____1234H______ mov dl,var ; DL=___78H_______ mov dh,var+3 ; DH=____12H______
3.16使用若干 MOV 指令实现交互指令“ XCHG EBX,[EDI] ”功能(p73)
答:
mov eax,ebx mov ebx,[edi] mov [edi],eax
🚫注意:XCHG:交换源操作数和目的操作数的内容。
3.17假设当前 ESP=0012FFB0H,说明下面每条指令后, ESP等于多少? push eax push dx push dword ptr 0f79h pop eax pop word ptr [bx] pop ebx
(P74)
答:
push eax ;esp=0012FFB0H-4=0012FFACH push dx ;esp=0012FFACH-2=0012FFAAH push dword ptr 0f79h ;esp=0012FFAAH-4=0012FFA6H pop eax ;esp=0012FFA6H+4=0012FFAAH pop word ptr [bx] ;esp=0012FFAAH+2=0012FFACH pop ebx ;esp=0012FFACH+4=0012FFB0H
🚫注意:堆栈端的范围由堆栈指针寄存器ESP的初值决定,这个位置就是堆栈底部。
-
push:进站指令,随着数据进站,堆栈顶部(指针ESP)逐渐减小,所以可以将其看成是一个倒扣的箱子,盘子从下面放进去。对应一条减法指令SUB和一条传送指令MOV
-
pop:出站指令
3.18已知数字 0~9 对应的格雷码依次为: 18H、34H、05H、06H、09H、0AH、0CH、11H、12H、14H; 请为如下程序的每条指令加上注释,说明每条指令的功能和执行结果。 ; 数据段 table byte 18h,34h,05h,06h,09h,0ah,0ch,11h,12h,14h ; 代码段 mov ebx,offset table mov al,8 xlat 为了验证你的判断, 不妨使用本书的 I/O 子程序库提供的子程序 DISPHB 显示换码后 AL 的值。如 果不使用 XLAT 指令,应如何修改?(P76)
答:
; 数据段 table byte 18h,34h,05h,06h,09h,0ah,0ch,11h,12h,14h ;定义格雷码表 ; 代码段 mov ebx,offset table ;ebx=格雷码表首地址 mov al,8 ;AL=8 xlat ;AL=[AL+EBX] ;不使用XLAT指令: mov ebx,offset table ; EBX=格雷码表首地址 mov eax,0 mov al,8 ; AL=8 mov al,[eax+ebx] ; AL=12H(8的格雷码)
3.19请分别用一条汇编语言指令完成如下功能:
(1)把 EBX 寄存器和 EDX 寄存器的内容相加,结果存入 EDX 寄存器。
(2)用寄存器 EBX 和 ESI 的基址变址寻址方式把存储器的一个字节与 AL 寄存器的内容相加, 并 把结果送到 AL 中。
(3)用 EBX 和位移量 0B2H 的寄存器相对寻址方式把存储器中的一个双字和 ECX 寄存器的内容 相加,并把结果送回存储器中。
(4)将 32 位变量 VARD 与数 3412H 相加,并把结果送回该存储单元中。
(5)把数 0A0H 与 EAX 寄存器的内容相加,并把结果送回 EAX 中。(p49,p81)
答:
;1 ADD EDX,EBX ;2 ADD AL,[ESX+ESI] ;3 ADD [EBX+0B2H],ECX ;4 add vard,3412h ;5 add eax,0a0h
3.20分别执行如下程序片断,说明每条指令的执行结果:(p80)
(1) mov eax,80h ;eax= add eax,3 ;eax= ,cf= ,sf= add eax,80h ;eax= ,cf= ,of= adc eax,3 ;eax= ,cf= ,zf= (2) mov eax,100 ;eax= add ax,200 ;eax= ,cf= (3) mov eax,100 ;eax= add al,200 ;eax= ,cf= (4) mov al,7fh ; al= sub al,8 ; al= ,cf= ,sf= sub al,80h ; al= ,cf= ,of= sub al,3 ; al= ,cf= ,zf=
答:
(1) mov eax,80h ;eax= 80h add eax,3 ;eax=83h ,cf=0 ,sf=0 add eax,80h ;eax=103h ,cf=0 ,of=0 adc eax,3 ;eax=106h ,cf=0 ,zf=0 (2) mov eax,100 ;eax=64H add ax,200 ;eax=128H ,cf=0 (3) mov eax,100 ;eax=64H add al,200 ;eax=2CH ,cf=1 (4) mov al,7fh ; al=7FH sub al,8 ; al=77H ,cf=0 ,sf=0 sub al,80h ; al=F7H ,cf=1 ,of=1 sub al,3 ; al=F4H ,cf=0 ,zf=0
🚫注意:
-
cf,of判断时,分别将数据看为无符号和有符号数进行判断。
(4)无符号数:119-128有借位
有符号数:119-(-128)溢出
-
sf与符号位相同
-
zf看运算结果是否为零
3.21给出下列各条指令执行后 AL 值,以及 CF、ZF、SF、OF 和 PF 的状态: mov al,89h add al,al add al,9dh cmp al,0bch sub al,al dec al inc al(同上题)
答:
mov al,89h ;AL=89h 1000 1001 add al,al ;AL=12h 、CF=1 、ZF=0 、SF=0 、OF=1 、PF =1 0001 0010 add al,9dh ;AL=0afh 、CF=0 、ZF=0 、SF=1 、OF=0 、PF =1 1010 1111 cmp al,0bch ;AL=0afh 、CF=1 、ZF=0 、SF=1 、OF=0 、PF =1 1010 1111 sub al,al ;AL=00h 、CF=0 、ZF=1 、SF=0 、OF=0 、PF =1 0000 0010 dec al ;AL=0ffh 、CF=0 、ZF=0 、SF=1 、OF=0 、PF =1 1111 1111 inc al ;AL=00h 、CF=0 、ZF=1 、SF=0 、OF=0 、PF =1 0000 0000
🚫注意:INC,DEC均不影响cf位
3.22有两个 64 位无符号整数存放在变量 buffer1 和 buffer2 中,定义数据、编写代码完成 EDX.EAX ← buffer1-buffer2 功能。(p82)
答:
.data buffer1 qword 6788300087883000h buffer2 qword 6788300097883100h .code strat: mov eax,dword ptr buffer1 ;低32位获取到eax中 mov edx,dword ptr buffer1+4 ;高32位获取到edx中 sub eax,dword ptr budder2 ;低32为相减,是否借位看cf sbb edx,dword ptr budder2+4 ;高32位相减并减去cf, end start
🚫注意:
sbb eax,ebx; eax=eax-ebx-cf
3.23分别执行如下程序片断,说明每条指令的执行结果: (p89)
(1) mov esi,10011100b ;esi= and esi,80h ;esi= or esi,7fh ;esi= xor esi,0feh ;esi= (2) mov eax,1010b ;eax= shr eax,2 ;eax= ,cf= shl eax,1 ;eax= ,cf= add eax,3 ;eax= ,cf= (3) mov eax,1011b ;eax= rol eax,2 ;eax= ,cf= rcr eax,1 ;eax= ,cf= or eax,3 ;eax= ,cf= (4) xor eax,eax ;eax= ,CF= ,OF= ; ZF= ,SF= ,PF=
答:
(1) mov esi,10011100b ;esi=9ch and esi,80h ;esi=80h or esi,7fh ;esi=ffh xor esi,0feh ;esi=01h (2) mov eax,1010b ;eax=1010b shr eax,2 ;eax=0010b ,cf=1 shl eax,1 ;eax=0100b ,cf=0 and eax,3 ;eax=0000b ,cf=0 (3) mov eax,1011b ;eax=1011b rol eax,2 ;eax=101100b ,cf=0 rcr eax,1 ;eax=10110b ,cf=0 or eax,3 ;eax=10111b ,cf=0 (4) xor eax,eax ;eax=0000b ,CF=0 ,OF=0 ; ZF=1 ,SF=0 ,PF=1
🚫注意:
-
AND、OR、XOR操作能让cf=of=0.
3.24 给出下列各条指令执行后 AX 的结果,以及状态标志 CF、OF、SF、ZF、PF 的状态。 mov ax,1470h and ax,ax or ax,ax xor ax,ax not ax test ax,0f0f0h
答:
mov ax,1470h ;AX=1470h and ax,ax ;AX=1470h 、CF=0 、ZF=0 、SF=0 、OF=0 、PF =0 or ax,ax ;AX=1470h 、CF=0 、ZF=0 、SF=0 、OF=0 、PF =0 xor ax,ax ;AX=0 、CF=0 、ZF=1 、SF=0 、OF=0 、PF =1 not ax ;AX=ffffh 、CF=0 、ZF=1 、SF=0 、OF=0 、PF =1 test ax,0f0f0h ;AX=0ffffh 、CF=0 、ZF=0 、SF=1 、OF=0 、PF =1
🚫注意:
not指令支持的操作是寄存器和存储单元,不影响标志位。(p88)
3.25逻辑运算指令怎么实现复位、置位和求反功能?(p89)
答:AND指令同“0”与实现复位,OR指令同“1”或实现置位,XOR同“1”异或实现求反。
3.26说明如下程序段的功能: mov ecx,16 mov bx,ax next: shr ax,1 rcr edx,1 shr bx,1 rcr edx,1 loop next mov eax,edx (p91)
答:该程序将AX的每一位依次重复一次,所得的32位结果保存于EAX中。
mov ecx,16 ;将16传送给ecx,下面next循环16次 mov bx,ax ;把ax传送给bx next: ;循环标识 shr ax,1 ;逻辑右移 rcr edx,1 ;带进位循环右移 shr bx,1 rcr edx,1 loop next mov eax,edx
3.27编程将一个 64 位数据逻辑左移 3 位,假设这个数据已经保存在 EDX.EAX 寄存器对中。(p91)
答:
;将一个 64 位数据逻辑左移 3 位 mov ecx,3 ;循环次数 next: shl eax,1 ;低32位逻辑左移,最高位位移到cf中 rcl edx,1 ;高32位带进位左循环位移,将cf值移到低位。 loop next
3.28编程将一个压缩 BCD 码变量(例如 92H)转换为对应的 ASCII 码,然后调用 DISPC 子程序(在输 入输出子程序库中)显示。(p77)
答:
.data bcd byte 92h .code mov al,bcd shr al,4 add al,30h call dispc mov al,bcd and al,0fh add al,30h call,dispc
3.29以 MOVS 指令为例,说明串操作指令的寻址特点, 并用 MOV 和 ADD 等指令实现 MOVSD 的功能 (假设 DF=0)。(p93)
答:MOVS指令的功能是:
ES:[EDI]←DS:[ESI];ESI←ESI±1/2/4,EDI←EDI±1/2/4
由此可看出串操作指令的寻址特点:
源操作数用寄存器ESI间接寻址,默认在DS指向的数据段,但可以改变;目的操作数用寄存器EDI间接寻址,只能在ES指向的附加数据段;每执行一次串操作,源指针ESI和目的指针EDI将自动修改:±1(字节),±2(字)或±4(双字)。指针的增量和减量控制由DF标志确定,DF=0,进行增量;DF=1,进行减量。
push eax mov eax,[esi] mov es:[edi],eax add esi,4 add edi,4
3.30说明如下程序执行后的显示结果:
; 数据段 msg byte 'WELLDONE',0 ; 代码段 mov ecx,(lengthof msg)-1 ;lengthof(msg)-1=9-1=8 mov ebx,offset msg again: ;转换为小写 mov al,[ebx] add al,20h mov [ebx],al add ebx,1 loop again mov eax,offset msg call dispmsg
如果将其中语句“ mov ebx,offset msg”改为“ xor ebx,ebx”,则利用 EBX 间接寻址的两个语句如何 修改成 EBX 寄存器相对寻址,就可以实现同样功能?
答:显示结果:welldone、
EBX寄存器相对寻址修改结果为:
; 数据段 msg byte 'WELLDONE',0 ; 代码段 mov ecx,(lengthof msg)-1 ;lengthof(msg)-1=9-1=8 xor ebx,ebx again: ;转换为小写 mov al,[ebx+msg] ;修改后 add al,20h mov [ebx+msg],al ;修改后 add ebx,1 loop again mov eax,offset msg call dispmsg
🚫注意:sIZEOF(占用的字节空间)=lengthop(多少个数据量)*type(类型所占字节数)
3.31下面程序的功能是将数组 ARRAY1 的每个元素加固定值( 8000H),将和保存在数组 ARRAY2。在 空白处填入适当的语句或语句的一部分。
; 数据段 array1 dword 1,2,3,4,5,6,7,8,9,10 array2 dword 10 dup(?) ; 代码段 mov ecx,lengthof array1 mov ebx,0 again: mov eax,array1[ebx*4] add eax,8000h mov ______________ add ebx,________ loop again
答:
; 数据段 array1 dword 1,2,3,4,5,6,7,8,9,10 array2 dword 10 dup(?) ; 代码段 mov ecx,lengthof array1 mov ebx,0 again: mov eax,array1[ebx*4] add eax,8000h mov ___[array2+ebx*4],eax___________ add ebx,__1______ loop again