无符号数和有符号数
一个字节所表示的无符号数:
1111 1111 255 (0xFF)
1111 1110 254 (0xFE)
...
0000 0000 0 (0x00)
一个字节所表示的有符号数:
0111 1111 +127 (0x7F)
...
0000 0010 +2 (0x02)
0000 0001 +1 (0x01)
0000 0000 0 (0x00)
1111 1111 -1 (0xFF)
1111 1110 -2 (0xFE)
...
1000 0000 -128 (0x80)
一个字所表示的有符号数:
0111 1111 1111 1111 +32767 (0x7FFF)
...
0000 0000 0000 0000 +2 (0x0002)
0000 0000 0000 0001 +1 (0x0001)
0000 0000 0000 0000 0 (0x0000)
1111 1111 1111 1111 -1 (0xFFFF)
1111 1111 1111 1110 -2 (0xFFFE)
...
1000 0000 0000 0000 -32768 (0x8000)
sub和neg指令
减法操作
sub r/m,r/m/imm
例: sub al,35
sub dx,ax
sub dx,[0x2002]
sub byte [0x2002],37
sub byte [0x2002],al
注:禁止 sub m,m
取补码指令
neg r/m
例: neg al
neg di
neg byte [0x2002]
;//以下两部分代码等效
mov dx,[0x2002]
neg dx
-----------------------------
mov dx.[0x2002]
mov ax,0
sub ax,dx
mov dx,ax
计算机如何区分对待有符号和无符号数
大多数指令既适用于无符号整数也适用于有符号整数。
指令执行的结果不管是用无符号整数来解释还是用有符号整数来解释都是正确的。
但是,也有一些指令有它们的无符号和有符号版本
乘法指令mul:它的有符号指令为imul
除法指令div:它的有符号指令为idiv
mov ax,-6002
mov bl,-10
div bl
以上代码有问题
16位的被除数(ax)除以8位的除数(bl)
商600存放到al中,但al即使存放无符号数,最大也只能存放255,显然无法存放。
所以我们使用32位除法,被除数在ax和dx中,除数为bx。所以将bl改为bx
同时被除数为32位应在ax和dx中,为此我们应将-6002由16位扩展到32位,从ax扩展到dx
-------------------------------------------------------------------------------------
扩展指令:
cbw:将AL中的有符号数扩展到AX
(若AL=FD(-3),拓展后,AX=FFFD(-3))
cwde:将AX中的有符号数扩展到EAX
(若AX=FFFD(-3),拓展后,EAX=FFFFFFFD(-3))
cdqe:将EAX中的有符号数扩展到RAX
(若EAX=FFFFFFFD(-3),拓展后,RAX=FFFFFFFFFFFFFFFD(-3))
cwd:将AX中的有符号数扩展到DX:AX
(若AX=FFFD(-3),拓展后,DX=FFFF,AX=FFFD(-3))
cdq:将EAX中的有符号数扩展到EDX:EAX
(若EAX=FFFFFFFD(-3),拓展后,DX=FFFFFFFF,AX=FFFFFFFD(-3))
cdo:将RAX中的有符号数扩展到RDX:RAX
(若EAX=FFFFFFFFFFFFFFFD(-3),拓展后,DX=FFFFFFFFFFFFFFFF,AX=FFFFFFFFFFFFFFFD(-3))
上面的代码改为
;//以下为有符号除法
mov ax,-6002
cwd
mov bx,-10
idiv bx
times 510-($-$$) db 0
db 0x55,0xaa
bochs调试
b设置断点到0x7c00
s单步执行 十六进制e88e 对应 十进制有符号数-6002
再单步执行 cwd的作用显而易见 如图
继续执行到最后
可以看到rax中的258真好对应商+600
rdx中fffe 对应 十进制有符号数-2
标志寄存器
16位标志寄存器FLAGS:
按位:
|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
| | | | |OF|DF|IF|TF|SF|ZF| |AF| |PF| |CF|
CF(Carry Flag):进位标志。
当一个算术操作在结果的最高位产生进位或借位时,此标志是1,否则为0
例如:假设al中的内容为二进制1000 0000
add al,al
1000 0000
1000 0000
---------
0000 0000 产生进位CF=0
PF(Parity Flag):奇偶标志。
当一个算术操作的结果在低8位中有偶数个“1”,此标志是1,否则为0
例如:假设al中的内容为二进制0010 0110
xor al,3
0010 0110
0010 0110
---------
0010 0101 奇数个‘1’ PF=0
OF(Overflow Flag):溢出标志。
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。
如果运算结果超过当前运算位数所能表示的范围,则称为溢出,
OF的值被置为1,否则,OF的值被清为0。
例如:假设ah中的内容为二进制1111 1101
add ah,5
-3
+5
---------
+2 ah可以容纳 OF=0
AF(Adjust Flag):调整标志。
当一个算术操作在结果的位3产生进位或借位时,此标志是1,否则为0,
此标志用于二进制编码的十进制算法里。
例如:
mov ah,247
sub ah,8
1111 0111
0000 1000
----------
1110 1111
已学指令对标志位的影响:
cbw/cwde/cdqe/cwd/cdq/cqo 不影响任何标志位
cld DF=0,对CF、OF、ZF、SF、AF、PF的影响未定义
std DF=1,不影响其他标志位
inc/dec CF标志不受影响;对OF、SF、 ZF、AF和PF的影响依计算结果而定。
add/sub OF、SF、ZF、AF、CF和PF的状态依计算结果而定。
div/idiv 对CF、OF、SF、ZF、AF和PF的影响未定义。
mov/movs 这类指令不影响任何标志位。
neg 如果操作数为0,则CF=0,否则CF=1;对OF、SF、ZF、AF和PF的影响依
xor OF=O,CF=0;对SF、ZF和PF依计算结果而定;对AF的影响未定义。
js:符号标志SE为1则转移;
jns:符号标志SF不为1 (为0)则转移。
jz:零标志ZF为1则转移,
jnz:零标志ZE不为1 (为0)则转移。
jo:溢出标志0F为1则转移,
jno:溢出标志OF不为1 (为0)则转移。
jc:进位标志CF为1则转移,
jnc:进位标志CF不为1 (为0)则转移。
jp:奇偶标志PF为1则转移,
jnp:奇偶标志PF不为1 (为0)则转移。
------------------------------------------------------------------------------------
jcxz(jump if CX is zero):当寄存器CX的内容为0时则转移
例如:
jcxz show
比较操作:cmp (影响到CF、OF、SF、ZF、AF)
cmp和sub一样也是减法,但是是根据比较结果设定标志位结果不会改变
cmp会将两个操作数看作无符号和有符号数比较
cmp r/m,r/m/imm
例如:
cmp al,35 (根据比较结果设定标志位)
cmpp dx,ax
cmp dx,ax
cmp byte [0x2005],37
cmp [0x2008],ax
;//例:
cmp dh,0
jl negb ;//dh和0比较如果小于0则跳转到negb执行
;//-----------------------------------
cmp dh,0x80
jae negb ;//
受cmp指令执行结果影响的转移指令