汇编语⾔(五)——算术运算类指令
汇编语⾔(五)—— 算术运算类指令
算术运算类指令
状态标志是处理器的基本标志,⼀⽅⾯作为加减运算和逻辑运算的辅助结果,另⼀⽅⾯可以构成各种条件,实现程序分⽀。五个基本的状态标志分别为进位标志CF、溢出标志OF、零标志ZF、符号标志SF和奇偶标志PF。
算术运算对数据进⾏加减乘除,是基本的数据处理⽅法,加减运算有“和”或“差”的结果的同时,还有进借位、溢出等状态标志是结果的
⼀部分。
进位和溢出标志
汇编语言结束指令处理器按照⽆符号整数求得结果,设置进位标志CF、溢出标志OF。汇编程序员在计算⽆符号数时,应关⼼进位标志;在计算有符号数时,应关注溢出标志。
进位标志CF(Carry Flag)
当加减法运算结果的最⾼有效位有进位(加法)或借位(减法)时,进位标志置为1,即 CF = 1;否则 CF = 0。
1. 针对⽆符号整数,判断加减结果是否超出表达范围(⽆符号整数的表达范围:N位⽆符号整数的表达范围位0 -1,如8位⽆符号整数的表达范围为0  255,16位⽆符号整数的表达范围为0 65535,32位⽆符号整数的表达范围位0-1)。
2. 有进位时,加上进位或借位后运算结果仍然正确。
; ⽆进位, CF = 0
;  8 位 2进制      两位 16 进制    10 进制
00111010          3A            58
+ 01111100        + 7C          + 124
= 10110110        = B6          = 182
; 有进位, CF = 1
;  8 位 2进制      两位 16 进制    10 进制
10101010          AA            170
+  01111100        +  7C          + 124
= 100100110        = 126          = 294 = 256 + 38  ; 结果为低位部分,即 38
溢出标志OF(Overflow Flag)
有符号数加减结果有溢出,则OF = 1;否则 OF = 0。
∼2N ∼∼∼232
1. 针对有符号整数,判断加减结果是否超出表达范围(有符号整数(补码)的表达范围:N位有符号整数的表达范围位-  -
1,如8位有符号整数的表达范围为-128 127,16位有符号整数的表达范围为-32768 32767,32位有符号整数的表达范围位-1)。
① 异号加法时,结果⼀定不会溢出;
② 同号加法时,结果同号则未溢出,结果异号则溢出。
③ 计算机只会加法运算,减法运算将被转换为加法运算。
④ 同号减法 = 异号加法,⼀定不会溢出;
⑤ 异号减法 = 同号加法,若结果与减数符号相同则溢出(e.g. 正 - 负 = 正 + 正 = 负;负 - 正 = 负 + 负 = 正),否则未溢出(e.g.正 - 负 = 正 + 正 = 正;负 - 正 = 负 + 负 = 负)。
2. 有溢出时,运算结果已经不正确。
; 有溢出, OF = 1
;  8 位 2进制      两位 16 进制    10 进制
00111010          3A            58
+ 01111100        + 7C          + 124
= 10110110        = B6          = 182            ; 182 > 127 溢出,结果错误
; ⽆溢出, OF = 0
;  8 位 2进制      两位 16 进制    10 进制
10101010          AA            -86
+  01111100        +  7C          + 124
= 100100110        = 126          =  38            ; -128 < 38 < 127 ,结果38
零标志、符号标志和奇偶标志
零标志ZF(Zero Flag)
若运算结果为0,则ZF = 1;否则ZF = 0。
; 8 位 2 进制数相加:结果不是 0 , ZF = 0
00111010 + 01111100 = 10110110
; 8 位 2 进制数相加:结果是 0 , ZF = 1
10000100 + 01111100 = [1]0000000            ; [1] 进位, CF = 1 ,0000000 结果
符号标志SF(Sign Flag)
运算结果最⾼位(即符号位)为1,则SF = 1;否则SF = 0。
; 8 位 2 进制数相加:最⾼位 = 1 , SF = 1
00111010 + 01111100 = 10110110
; 8 位 2 进制数相加:最⾼位 = 0 , SF = 0
10000100 + 01111100 = [1]0000000            ; [1] 进位, CF = 1 ,0000000 结果
奇偶标志PF(Parity Flag)
当运算结果最低字节(低⼋位)中“1”得个数为零或偶数时,PF = 1;否则PF = 0。
;
8 位 2 进制数相加:“ 1 ” 的个数为 5 , PF = 0
00111010 + 01111100 = 10110110
; 8 位 2 进制数相加:“ 1 ” 的个数为 0 , PF = 1
10000100 + 01111100 = [1]0000000            ; [1] 进位, CF = 1 ,0000000 结果
加减运算结果对状态标志的影响
;        8 位加法运算及结果          CF OF ZF SF PF
00111010 + 01111100 = [0]10110110  0  1  0  1  0  ; 正(0) + 正(0) = 负(1) OF = 1
10101010 + 01111100 = [1]00100110  1  0  0  0  0  ; 负(1) + 正(0) OF = 0
10000100 + 01111100 = [1]00000000  1  0  1  0  1  ; 负(1) + 正(0) OF = 0
影响状态标志的指令
2N −1∼2N −1∼∼231∼231
需要关注的影响状态标志的主要指令:加减运算指令、逻辑运算指令、移位指令等。
只⽤于影响状态标志的特殊指令:
① ⽐较指令CMP:进⾏减法运算,⽤于判断两个数据⼤⼩是否相等;
② 测试指令TEST:进⾏逻辑与运算,⽤于判断某位为0或为1等。
ADD指令
加法指令主要有三条:① 加法指令 ADD;② 带进位加法指令 ADC;③ 增量指令 INC。
1. ADD、ADC指令均按定义影响全部状态标志位,只有INC指令不影响进位标志CF。
2. 加法指令ADD:\add dest, src ; 把⽬的操作数加上源操作数,将“和”送到⽬的操作数。
add reg, imm/reg/mem  ; reg <- reg + imm/reg/mem
add mem, imm/reg      ; mem <- mem + imm/reg
3. 加法指令ADD按照定义影响5个状态标志位,⽀持8位、16位和32位的数据运算,两个操作数不能同时是内存单元。
; e.g.
mov eax, 0aaff7348H
add al, 27H          ; 8 位加法, 48H + 27H = 6FH -> eax = aaff736fH
; 6FH -> 01101111 -> OF = 0, SF = 0, ZF = 0, PF = 1, CF = 0
add ax, 3fffH        ; 16 位加法, 736FH + 3FFFH = B36EH -> eax = aaffb36eH
; B36EH -> 10110011 01101110
; -> OF = 1, SF = 1, ZF = 0, PF = 0, CF = 0
add eax, 88000000H    ; 32 位加法, aaffb36eH + 8800000H = 32ffb36eH(eax)
; 32FFB36EH -> 00110010 11111111 10110011 01101110
; -> OF = 1, SF = 0, ZF = 0, PF = 0, CF = 1
4. ⼤写字母转换为⼩写字母可以使⽤ADD。
add al, 20h          ; 'a' - 'A' = 20H , al = 'A'
; 'A' - 41H, 'a' - 61H
; ⼩写 = ⼤写 + 20H
SUB指令
减法指令主要有5条:① 减法指令 SUB;② 带借位减法指令 SBB;③ 减量指令 DEG;④ 求补指令 NEG;⑤ ⽐较指令 CMP。
1. SUB、SBB、NEG、CMP指令均按定义影响全部状态标志位,只有DEC指令不影响CF标志。
2. 减法指令SUB(subtract):sub dest, src ; 把⽬的操作数减去源操作数,将“差”送到⽬的操作数。
sub reg, imm/reg/mem  ; reg <- reg - imm/reg/mem
sub mem, imm/reg      ; mem <- mem - imm/reg
3. 减法指令SUB按照定义影响5个状态标志位,⽀持8位、16位和32位的数据运算,两个操作数不能同时是内存单元。
; e.g.
; 计算机中将减法转换为加法运算
mov eax, 0aaff7348H
sub al, 27H            ; 8 位减法, 48H - 27H = 21H -> eax = aaff7321H
; 21H -> 00100001 -> OF = 0, SF = 0, ZF = 0, PF = 1, CF = 0
sub ax, 3fffH          ; 16 位减法, 7321H - 3FFFH = 3322H -> eax = aaff3322H
; B36EH -> 00110011 00100010
; -> OF = 0, SF = 0, ZF = 0, PF = 1, CF = 0
sub eax, 0bb000000H    ; 32 位减法, aaff3322H - bb00000H = efff3322H(eax)
; 32FFB36EH -> 11101111 11111111 00110011 00100010
; -> OF = 0, SF = 1, ZF = 0, PF = 1, CF = 1
4. ⼩写字母转换为⼤写字母可以使⽤SUB。
sub al, 20h          ; 'a' - 'A' = 20H , al = 'a'
; 'A' - 41H, 'a' - 61H
; ⼤写 = ⼩写 - 20H
INC、DEC和NEG指令
增量指令INC(increment)
只有⼀个操作数(寄存器或存储单元),相当于⾼级语⾔中的i++。
1. 增量指令INC:inc dest ; 对操作数加⼀再将结果返回原处。
inc reg/mem          ; 加 1 : reg/mem <- reg/mem + 1
2. 增量指令INC⽤于计数器和地址指针的调整,不影响进位标志CF,影响其他状态标志位。
减量指令DEC(decrement)
只有⼀个操作数(寄存器或存储单元),相当于⾼级语⾔中的i- -。
1. 减量指令DEC:dec dest ; 对操作数减⼀再将结果返回原处。
dec reg/mem          ; 减 1 : reg/mem <- reg/mem - 1 ,
2. 减量指令DEC⽤于计数器和地址指针的调整,不影响进位标志CF,影响其他状态标志位。
INC和DEC⽤于指针调整和计数增减
; 字符串复制
.data
srcmsg  byte 'Try your best, why not.', 0
dstmsg  byte sizeof srcmsg dup(?)          ; 申请字节空间
.code
mov ecx, lengthof srcmsg          ; ECX = 字符个数,控制循环次数
mov esi, offset srcmsg            ; 将 srcmsg 的⾸地址给 esi
; 即 esi 指向 srcmsg 的⾸地址位置
mov edi, offset dstmsg            ; 将 dstmsg 的⾸地址给 edi
; 即 edi 指向 dstmsg 的⾸地址位置
again:  mov al, [esi]                      ; 将源字符串 esi 所存地址处的字符送给 al
mov [edi], al                      ; 将 al 所存的字符送给 edi 所存的地址单元
inc esi                            ; esi + 1
inc edi                            ; edi + 1
loop again                        ; loop 循环指令, exc - 1 ,循环 ecx 个数
mov eax, offset dstmsg
call dispmsg
求补指令NEG(negative)
只有⼀个操作数(寄存器或存储单元)。
1. 求补指令NEG:neg dest ; 对操作数执⾏求补运算,即⽤0减去操作数。
neg reg/mem          ; reg/mem <- 0 - reg/mem
2. 求补指令NEG⽤于对负数求补码或由补码求其绝对值,不影响进位标志CF,影响其他状态标志位。
NEG⽤于负数的求补运算
; 已知 100 的 8 位编码,求 -100 的 8 位补码
mov al, 64H          ; al = 64H = 100
neg al                ; al = 0 - 64H = 9CH = -100
; 9CH -> 10011100
; OF = 0, SF = 1, ZF = 0, PF = 1, CF = 1
;
已知 -100 的 32 位补码,求其绝对值,即 100
mov eax, 0ffffff9cH  ; eax = ffffff9cH = -100
neg eax              ; eax = 0 - ffffff9cH = 64H = 100
; 64H -> 01100100
; OF = 0, SF = 0, ZF = 0, PF = 0, CF = 1
参考

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。